Leetcode 39: python可变类型复制(浅拷贝和深拷贝)

来源:互联网 发布:手机域名注册查询 编辑:程序博客网 时间:2024/06/06 09:43

刚刚在leetcode上写了一道算法题:39. Combination Sum,因为踩了python中复制的坑,花了很长时间才爬出来=。=

题目:

Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.The same repeated number may be chosen from C unlimited number of times.

起因是用python做完题后看了一下c++的解法:

class Solution {public:    std::vector<std::vector<int> > combinationSum(std::vector<int> &candidates, int target) {        std::sort(candidates.begin(), candidates.end());        std::vector<std::vector<int> > res;        std::vector<int> combination;        combinationSum(candidates, target, res, combination, 0);        return res;    }private:    void combinationSum(std::vector<int> &candidates, int target, std::vector<std::vector<int> > &res, std::vector<int> &combination, int begin) {        if (!target) {            res.push_back(combination);            return;        }        for (int i = begin; i != candidates.size() && target >= candidates[i]; ++i) {            combination.push_back(candidates[i]);            combinationSum(candidates, target - candidates[i], res, combination, i);            combination.pop_back();        }    }};

用了回溯的方法,非常完美啊有没有,于是想用python改写这个算法

class Solution(object):    def combinationSum(self, candidates, target):        """        :type candidates: List[int]        :type target: int        :rtype: List[List[int]]        """        def getComb(solution, candidates, index, target, res):            if target < 0:                return            elif target == 0:                res.append(solution)                return            for i in xrange(index, len(candidates)):                if target < candidates[i]:                    break                solution.append(candidates[i])                getComb(solution, candidates, i, target-candidates[i], res)                   solution.pop()        candidates.sort()        res = []        solution=[]        getComb(solution, candidates, 0, target, res)        return res

看起来是一模一样啊,可是得到的结果始终是:

[[],[]]

debug了好久,终于发现是这里出现了问题:

res.append(solution)

这里相当于将solution直接复制到res中,但是对象的引用并没有变,所以当执行

solution.append(candidates[i])

时,不仅会该改变solution对象,同时也会改变res,导致得不到想要的结果。

解决:

1.使用浅拷贝(因为这里的solution类型为List[int],所以使用浅拷贝就OK啦):

s = copy.copy(solution)res.append(s)

2.不在函数中直接修改solution,而是通过递归改变solution的值:

class Solution(object):    def combinationSum(self, candidates, target):        """        :type candidates: List[int]        :type target: int        :rtype: List[List[int]]        """        def getComb(solution, candidates, index, target, res):            if target < 0:                return            elif target == 0:                res.append(solution)                return            for i in xrange(index, len(candidates)):                if candidates[i] > target:                    break                getComb(solution+[candidates[i]], candidates, i, target-candidates[i], res)        candidates.sort()        res = []        getComb([], candidates, 0, target, res)        return res

这种写法还隐式地实现了回溯,真是很巧妙啊!