【LeetCode 中等题】21-组合总和II

声明:

今天是中等题第21道题。给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合,candidates 中的每个数字在每个组合中只能使用一次。以下所有代码经过楼主验证都能在LeetCode上执行成功,代码也是借鉴别人的,在文末会附上参考的博客链接,如果侵犯了博主的相关权益,请联系我删除

(手动比心ღ( ´・ᴗ・` ))

正文

题目:给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合,candidates 中的每个数字在每个组合中只能使用一次。

说明:

  • 所有数字(包括目标数)都是正整数。
  • 解集不能包含重复的组合。 

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
  [1,2,2],
  [5]
]

解法1。和上一篇博客组合总和I相似的思路,只是递归过程中可选元素不包括当前已经被选择过的元素了,代码如下。

执行用时: 168 ms, 在Combination Sum II的Python3提交中击败了37.76% 的用户

class Solution:
    def combinationSum2(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        res = []
        path = []
        candidates.sort()
        self._combinationSum2(candidates, target, 0, path, res)
        return res

    def _combinationSum2(self, nums, target, index, path, res):
        if target == 0 and path not in res:    # 如果不加判断是否重复的逻辑的话结果会有重复
            res.append(path)
            return
        if path and target < path[-1]:
            return

        for i in range(index,len(nums)):    # index从i+1开始,说明把当前被target减过(选择过)的元素nums[i]剔除出去了,从i+1开始索引元素
            self._combinationSum2(nums, target-nums[i], i+1, path+nums[i], res)


    # _combinationSum2版本2,因为上面这个函数的写法是在第一条if语句中去重,其实可以优化一下,把去重写在for循环中,之所以会有重复是因为比如原数组中有2个1,target=8,那么结果会有2个[1,7],但这2个[1,7]中的1不是同一个1,优化代码如下:
    def _combinationSum2(self, nums, target, index, path, res):
        if target == 0:
            res.append(path)
            return
        if path and target < path[-1]:
            return
        for i in range(index, len(nums)):
            if i>index and nums[i] == nums[i-1]:    # i必须>index不然i-1就out of index了
                continue
            self._combinationSum2(nums, target-nums[i], i+1, path+[nums[i]], res) 

 解法2。用迭代的方式重现递归的过程,用stack存放每个被遍历元素的状态(index,path,remain)代码如下。

执行用时: 88 ms, 在Combination Sum II的Python3提交中击败了82.31% 的用户

class Solution:
    def combinationSum2(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        res = []
        path = []
        candidates.sort()
        n = len(candidates)
        stack = [(0,path,target)]
        while stack:
            index, path, remain = stack.pop()
            for i in range(index,n):
                if i > index and candidates[i] == candidates[i-1]:
                    continue
                if path and remain < path[-1]:
                    break
                
                if remain == candidates[i]:
                    res.append(path + [candidates[i]])
                
                stack += [(i+1, path+[candidates[i]], remain-candidates[i])]
        return res

结尾

解法1&解法2:https://blog.csdn.net/qq_17550379/article/details/82591181

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值