zl程序教程

您现在的位置是:首页 >  后端

当前栏目

python算法之组合总和

Python算法 组合 总和
2023-09-11 14:22:10 时间


给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

所有数字(包括 target)都是正整数。
解集不能包含重复的组合。 
示例 1:

输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[[7],[2,2,3]]
示例 2:

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


class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        self.res = []
        if len(candidates) <= 0:
            return res
        candidates.sort()
        self.dfs(candidates,[],target,0)  # 递归回溯
        return self.res
            
    def dfs(self,candidates,sublist,target,last):  # last表示当前sublist的最后一个元素
        if target == 0:
            self.res.append(sublist) 
        if target < candidates[0]:  # 剪枝操作,目标值小于拥有的最小元素
            return 
        for num in candidates:  # 数字可重复使用,则每次从头遍历
            if num > target:  # 剪枝操作,当当前数值大于目标值,则后续无需遍历
                return 
            if num < last: # 剪枝操作:若当前数值小于当前sublist的最后一个元素,则继续遍历,防止出现重复解决方案,如[2,2,3],[3,2,2]
                continue
            self.dfs(candidates,sublist+[num],target-num,num)

def t2(li,v):
    li= sorted(li)
    ans=[]
    def f(s,use,remain):  #s是li的坐标
        for i in range(s,len(li)):
            c=li[i]
            if c==remain:
                ans.append(use+[c])
            if c<remain:
                f(i,use+[c],remain-c)
            if c>remain:
                return
    f(0,[],v)
    return ans


if __name__ == '__main__':
    li=[2,3,4,5,6,7]
    r3=t2(li,10)
    print(r3)

递归函数 dfs(candidates,sublist,target,last),其中sublist记录当前满足条件的子数组,last为当前子数组的最后一个元素。

剪枝操作1:目标值小于元素数组的最小元素,则无需继续遍历

剪枝操作2:当前元素大于目标值,则后续元素一定大于目标值(数组已排序),不会满足条件,无需继续遍历

剪枝操作3:若当前数值小于当前sublist的最后一个元素,则继续遍历,防止出现重复解决方案,如[2,2,3],[3,2,2]