-
39组合总数
- 代码随想录 (programmercarl.com)
-
第一印象
- 本题的元素能够重复,那么回来条件便是是大于等于目标值。依旧是运用path和result存储值。
-
讲解观后感
- sum值能够不作为参数传入递归函数中,直接用target -。但是保有sum值能够便利剪枝。
- 剪枝操作能够先经过排序使数组单调递加。再运用当时sum与当时值的和来提早停止for循环.
-
解题代码
-
func combinationSum(candidates []int, target int) [][]int {
ans := make([][]int, 0)
if len(candidates)==0 {
return ans
}
path := []int{}
sum := 0
var dfs func(candidates []int, idx int, sum int, target int)
dfs = func(candidates []int, idx int, sum int, target int) {
if sum > target {
return
}
if sum == target {
temp := make([]int, len(path))
copy(temp, path)
ans = append(ans, temp)
return
}
for i:=idx;i<len(candidates);i++ {
sum += candidates[i]
path = append(path, candidates[i])
dfs(candidates, i, sum, target)
path = path[:len(path)-1]
sum -= candidates[i]
}
}
dfs(candidates, 0, sum, target)
return ans
}
- 剪枝:
-
func combinationSum(candidates []int, target int) [][]int {
ans := make([][]int, 0)
if len(candidates)==0 {
return ans
}
path := []int{}
sum := 0
sort.Ints(candidates)
var dfs func(candidates []int, idx int, sum int, target int)
dfs = func(candidates []int, idx int, sum int, target int) {
if sum == target {
temp := make([]int, len(path))
copy(temp, path)
ans = append(ans, temp)
return
}
for i:=idx;i<len(candidates)&&sum+candidates[i]<=target;i++ {
sum += candidates[i]
path = append(path, candidates[i])
dfs(candidates, i, sum, target)
path = path[:len(path)-1]
sum -= candidates[i]
}
}
dfs(candidates, 0, sum, target)
return ans
}
-
40组合总数II
- 代码随想录 (programmercarl.com)
-
第一印象
- 本题每个数字只能运用一次,那么递归传参就得+1
-
讲解观后感
- 这题的去重操作非常巧妙。关于树形结构中树层与树枝的评论非常形象。
-
解题代码
- 运用used数组
-
func combinationSum2(candidates []int, target int) [][]int {
ans := make([][]int, 0)
if len(candidates)==0 {
return ans
}
path := []int{}
sum := 0
sort.Ints(candidates)
used := make([]bool, len(candidates))
var dfs func(candidates []int, target int,idx int, sum int)
dfs = func(candidates []int, target int,idx int, sum int) {
if sum == target {
temp := make([]int, len(path))
copy(temp, path)
ans = append(ans, temp)
return
}
for i:=idx;i<len(candidates)&&sum+candidates[i]<=target;i++ {
if i > 0 && candidates[i] == candidates[i-1] && used[i-1] == false {
continue
}
sum += candidates[i]
path = append(path, candidates[i])
used[i] = true
dfs(candidates, target, i+1, sum)
used[i] = false
path = path[:len(path)-1]
sum -= candidates[i]
}
}
dfs(candidates, target, 0, sum)
return ans
}
- 不运用used数组
-
func combinationSum2(candidates []int, target int) [][]int {
ans := make([][]int, 0)
if len(candidates)==0 {
return ans
}
path := []int{}
sum := 0
sort.Ints(candidates)
var dfs func(candidates []int, target int,idx int, sum int)
dfs = func(candidates []int, target int,idx int, sum int) {
if sum == target {
temp := make([]int, len(path))
copy(temp, path)
ans = append(ans, temp)
return
}
for i:=idx;i<len(candidates)&&sum+candidates[i]<=target;i++ {
if i != idx && candidates[i] == candidates[i-1] {
continue
}
sum += candidates[i]
path = append(path, candidates[i])
dfs(candidates, target, i+1, sum)
path = path[:len(path)-1]
sum -= candidates[i]
}
}
dfs(candidates, target, 0, sum)
return ans
}
- 不运用sum传参
-
var (
res [][]int
path []int
)
func combinationSum2(candidates []int, target int) [][]int {
res, path = make([][]int, 0), make([]int, 0, len(candidates))
sort.Ints(candidates)
dfs(candidates, 0, target)
return res
}
func dfs(candidates []int, start int, target int) {
if target == 0 {
tmp := make([]int, len(path))
copy(tmp, path)
res = append(res, tmp)
return
}
for i := start; i < len(candidates); i++ {
if candidates[i] > target {
break
}
if i != start && candidates[i] == candidates[i-1] {
continue
}
path = append(path, candidates[i])
dfs(candidates, i+1, target - candidates[i])
path = path[:len(path) - 1]
}
-
131切开回文串
- 代码随想录 (programmercarl.com)
-
讲解观后感
- 本题也是经典的运用回溯算法的标题。而关于回溯的用法中,首要遇到的难点便是切开终究应该怎么表示。只要把index和i构成的区间是切开后的区间了解明白,就能解决了。
- 卡尔也帮我们列出了这道题的几个难点,协助我们了解。
-
切开问题能够抽象为组合问题
怎么模拟那些切开线
切开问题中递归怎么停止
在递归循环中怎么截取子串
怎么判断回文
-
解题代码
-
var (
path []string
res [][]string
)
func partition(s string) [][]string {
path, res = make([]string, 0), make([][]string, 0)
dfs(s, 0)
return res
}
func dfs(s string, start int) {
if start == len(s) {
tmp := make([]string, len(path))
copy(tmp, path)
res = append(res, tmp)
return
}
for i := start; i < len(s); i++ {
str := s[start : i+1]
if isPalindrome(str) {
path = append(path, str)
dfs(s, i+1)
path = path[:len(path)-1]
}
}
}
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
}