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]
    }
}
相关推荐
win x1 天前
JavaSE(基础)高频面试点及 知识点
java·面试·职场和发展
好好研究1 天前
Spring Boot - Thymeleaf模板引擎
java·spring boot·后端·thymeleaf
爬山算法1 天前
Hibernate(76)如何在混合持久化环境中使用Hibernate?
java·后端·hibernate
编程彩机1 天前
互联网大厂Java面试:从分布式缓存到消息队列的技术场景解析
java·redis·面试·kafka·消息队列·微服务架构·分布式缓存
她说..1 天前
策略模式+工厂模式实现单接口适配多审核节点
java·spring boot·后端·spring·简单工厂模式·策略模式
csdn_aspnet1 天前
ASP.NET 8 - Cookie 身份验证
后端·asp.net·cookie·.net8
笔画人生1 天前
Cursor + 蓝耘API:用自然语言完成全栈项目开发
前端·后端
xiaoye-duck1 天前
C++ string 底层原理深度解析 + 模拟实现(上)——面试 / 开发都适用
c++·面试·stl
小旭95271 天前
Java 反射详解
java·开发语言·jvm·面试·intellij-idea
有来技术1 天前
ASP.NET Core 权限管理系统(RBAC)设计与实现|vue3-element-admin .NET 后端
vue.js·后端·c#·asp.net·.net