LeetCode39 组合总和(带扩展)

leetcode.cn/problems/co...

解法一:回溯

这道题的关键在于 candidates 中的元素不重复,但一个元素可以复用多次,概括就是元素无重可复选 , 之前子集/组合问题(参考这篇文章),为了避免重复选,我们每次循环 ioffset 开始遍历,循环中递归下一层回溯树是从 i + 1offset + 1 开始遍历,从而保证 nums[offset] 这个元素不会被重复使用。

现在想让每个元素被重复使用,只要把 i + 1 改成 i 即可,在遍历这棵决策树的过程中,当前已经选择过的元素就可以在下一层递归被再次选择。

go 复制代码
func combinationSum(candidates []int, target int) [][]int {
    var res [][]int
    var pathSum int
    path := make([]int, 0)
    backtrack(candidates, 0, target, path, &pathSum, &res)
    return res
}

func backtrack(nums []int, offset int, target int, path []int, pathSum *int, res *[][]int) {
    if *pathSum == target{ // 找到目标和
        tmp := make([]int, len(path))
        copy(tmp, path)
        *res = append(*res, tmp)
        return
    }
    if *pathSum > target{ // 超过目标和提前结束
        return
    }
    for i:=offset; i<len(nums); i++{
        // 做选择
        path = append(path, nums[i])
        *pathSum+=nums[i]
        backtrack(nums, i, target, path, pathSum, res) // 递归起点仍在当前位置,当前元素可被下一层复选
        // 撤销选择
        path = path[:len(path)-1]
        *pathSum-=nums[i]
    }
}

扩展

来看这道题组合总和 II 题意变成元素有重不可复选 ,我们参考这篇文章扩展2中的解法,先对原数组排序,相同的元素放在相邻的位置上,然后在遍历决策树的过程中进行剪枝

go 复制代码
func combinationSum2(candidates []int, target int) [][]int {
    sort.Ints(candidates)
    var res [][]int
    var pathSum int
    path := make([]int, 0)
    backtrack(candidates, 0, target, path, pathSum, &res)
    return res
}

func backtrack(nums []int, offset int, target int, path []int, pathSum int, res *[][]int){
    if pathSum == target{ 
        tmp := make([]int, len(path))
        copy(tmp, path)
        *res = append(*res, tmp)
        return
    }
    if pathSum > target{ // 超过目标和,直接结束
        return
    }
    for i:=offset; i<len(nums); i++{
        if i > offset && nums[i] == nums[i-1]{ // 值相同的树枝,只遍历第一条
            continue
        }
        path = append(path, nums[i])
        pathSum+=nums[i]
        backtrack(nums, i+1, target, path, pathSum, res)
        path = path[:len(path)-1]
        pathSum-=nums[i]
    }
}
相关推荐
胡gh4 小时前
页面卡成PPT?重排重绘惹的祸!依旧性能优化
前端·javascript·面试
ningqw4 小时前
SpringBoot 常用跨域处理方案
java·后端·springboot
你的人类朋友4 小时前
vi编辑器命令常用操作整理(持续更新)
后端
胡gh4 小时前
简单又复杂,难道只能说一个有箭头一个没箭头?这种问题该怎么回答?
javascript·后端·面试
言兴4 小时前
# 深度解析 ECharts:从零到一构建企业级数据可视化看板
前端·javascript·面试
一只叫煤球的猫5 小时前
看到同事设计的表结构我人麻了!聊聊怎么更好去设计数据库表
后端·mysql·面试
uzong5 小时前
技术人如何对客做好沟通(上篇)
后端
颜如玉6 小时前
Redis scan高位进位加法机制浅析
redis·后端·开源
Moment6 小时前
毕业一年了,分享一下我的四个开源项目!😊😊😊
前端·后端·开源
why技术7 小时前
在我眼里,这就是天才般的算法!
后端·面试