代码随想录算法训练营|day27

第七章 回溯算法

  • 39.组合总和
  • 40.组合总和II
  • 131.分割回文串
  • 代码随想录文章详解
  • 总结

39.组合总和

对数组排序,方便剪枝;剪枝:当前path求和大于target进行下一轮循环
数组中元素可以重复取值,所以递归时可以取当前值

func combinationSum(candidates []int, target int) [][]int {
	res := [][]int{}
	path := []int{}
	sort.Ints(candidates)
	var help func(candidates []int, target, sum, startIndex int)
	help = func(candidates []int, target, sum, startIndex int) {
		if sum == target {
			tmp := make([]int, len(path))
			copy(tmp, path)
			res = append(res, tmp)
			return
		}
		for i := startIndex; i < len(candidates) && sum+candidates[i] <= target; i++ {
			sum += candidates[i]
			path = append(path, candidates[i])
			help(candidates, target, sum, i)
			sum -= candidates[i]
			path = path[:len(path)-1]
		}
	}
	help(candidates, target, 0, 0)
	return res
}

40.组合总和II

数组中有重复元素,要求结果集合不能重复
注意:去重同一层元素,used[i - 1] = false,说明是从前一个元素回溯回来的,若used[i - 1] = true说明是进入下一个递归取值

func combinationSum2(candidates []int, target int) [][]int {
	res := [][]int{}
	path := []int{}
	used := make([]bool, len(candidates))
	sort.Ints(candidates)
	var help func(candidates []int, target, sum, startIndex int)
	help = func(candidates []int, target, sum, startIndex int) {
		if sum == target {
			tmp := make([]int, len(path))
			copy(tmp, path)
			res = append(res, tmp)
			return
		}
		for i := startIndex; i < len(candidates) && sum+candidates[i] <= target; i++ {
			if i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false {
				continue
			}
			sum += candidates[i]
			used[i] = true
			path = append(path, candidates[i])
			help(candidates, target, sum, i+1)
			path = path[:len(path)-1]
			used[i] = false
			sum -= candidates[i]
		}
	}
	help(candidates, target, 0, 0)
	return res
}

131.分割回文串

当切割点在string长度位置,说明找到一组符合要求的结果
如果是回文串,递归寻找后面的回文串,回溯;否则跳过当前元素

func partition(s string) [][]string {
	res := [][]string{}
	path := []string{}

	var help func(s string, startIndex int)
	help = func(s string, startIndex int) {
		if startIndex == len(s) {
			tmp := make([]string, len(path))
			copy(tmp, path)
			res = append(res, tmp)
			return
		}
		for i := startIndex; i < len(s); i++ {
			str := s[startIndex : i+1]
			if isPalindrome(str) {
				path = append(path, str)
				help(s, i+1)
				path = path[:len(path)-1]
			}
		}
	}
	help(s, 0)
	return res
}

func isPalindrome(s string) bool {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		if s[i] != s[j] {
			return false
		}
	}
	return true
}

代码随想录文章详解

39.组合总和
40.组合总和II
131.分割回文串

总结

组合、切割、子集、排列、棋盘:N皇后,解数独等等
学习go语言map实现set
基本能实现回溯,代码随想录yyds

你可能感兴趣的:(代码随想录练习,算法,go)