数字组合

来源:互联网 发布:mts钢结构设计软件 编辑:程序博客网 时间:2024/06/04 17:56

题目描述:给出一组候选数字(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T。C中的数字可以无限制重复被选取。例如,给出候选数组[2,3,6,7]和目标数字7,所求的解为:[7],[2,2,3]

样例:给出候选数组[2,3,6,7]和目标数字7,返回 [[7],[2,2,3]]


跟问题“组合”(详见:点击打开链接)从本质上讲是一样的,都是“深搜” + “递归”的方法。只不过这个问题看上去要更难一些,因为允许有重复,且每一种数字组合的个数不一定相等。说的专业一点,我们应该把此类问题成为“回溯法”,和之前最大的区别,就是这里数字组合的问题需要用到“剪枝”的方法,所谓“剪枝”,其实就是当现在的情况已经不可能完成目标时,返回父节点(比如,这个问题中,当某一时刻的数字组合已经大于目标数字,我们就回溯,而不一定只是等于目标元素时,才回溯)。

不过我本人一向不喜欢把问题的方法归纳的太细,因为记不住嘛。所以我并不把这个问题和前面的组合分开,我依然认为他们是同一类问题。方法也是类似的,还是需要一个辅助函数helper(),这个辅助函数的参量设置和我们之前处理组合问题时,从原理上讲是一模一样的:path, begin, result, target, candidates,具体意思和之前一样,我不解释了(我这里假设你已经搞懂之前的“组合”问题:点击打开链接,以及“电话号码的字母组合”问题:点击打开链接)

这个函数做的事情,就是在某一时刻,以当前的path为参数,从candidates的begin位置开始到结束作为当前候选列表,寻找可能的“成功”组合,若找寻过程中,组合已经大于target了,则回溯。


理解起来确实比较难,看代码吧,也许注释会说的更清楚:

class Solution:    # @param candidates, a list of integers    # @param target, integer    # @return a list of lists of integers    def combinationSum(self, candidates, target):        candidates.sort()        path, result = [], []        begin = 0        self.helper(begin, candidates, target, path, result)        return result    def helper(self, begin, candidates, target, path, result):        # 剪枝        if sum(path) > target:            return        # 若满足条件:先复制,再将复制的结果加入结果列表        if sum(path) == target:            temp = path[:]            result.append(temp)            return        for i in candidates[begin:]:            path.append(i)            # 带着半成品path继续探索:往这个半成品中添加元素,看能否成功            self.helper(begin, candidates, target, path, result)            # 返回上一层,自然要把这一层添加的值删去            path.pop(-1)            # 这一层的情况已经处理过了,所以不论是形成“成功”的组合,还是被“剪枝”,都应该从candidates            # 的下一位开始,begin += 1            begin += 1        # write your code here


0 0
原创粉丝点击