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]
    }
}
相关推荐
程序视点18 分钟前
电脑硬件检测必备!图吧工具箱11年免费良心软件!100+免费工具合集
前端·windows·后端
IguoChan26 分钟前
话一话职场PUA
后端
陈随易39 分钟前
国产之光,把AI融入到语言级别的编程语言-MoonBit
前端·后端·程序员
我来整一篇1 小时前
ASP.NET Core中使用NLog和注解实现日志记录
后端·asp.net
_一条咸鱼_1 小时前
Android Runtime冷启动与热启动差异源码级分析(99)
android·面试·android jetpack
星眠1 小时前
手写发布订阅设计模式
javascript·设计模式·面试
小青年4691 小时前
springboot3 vue3校园失物招领系统实战开发教程
后端
天天摸鱼的java工程师1 小时前
如何实现一个分布式锁?——来自 Java 老兵的实战总结 🚀🔐
java·后端·面试
北京_宏哥1 小时前
🔥Python零基础从入门到精通详细教程10 - python数据类型之数字(Number)-整型(int)详解
前端·python·面试