第一次跑去力扣刷题,就随便点进去了每日一题,题目是这样子的:
给定一个无重复元素的数组 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]
]
提示:
1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate 中的每个元素都是独一无二的。
1 <= target <= 500
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我使用的python3.7。参考了这篇博客:https://www.cnblogs.com/eilearn/p/9485946.html
直接使用递归计算,一开始的代码:
class Solution:
def combinationSum(self, candidates, target):
ans_list = [] # 求解的答案
ls = [] # 临时用的列表
self.diguii(candidates=candidates, target=target, pos=0, sum0=0, temp_list=ls, ans_list=ans_list)
return ans_list
def diguii(self, candidates, target, pos, sum0, temp_list, ans_list): # pos 是遍历位置, sum是当前的和, temp是列表
if sum0 == target: # 数据和等于目标值
ans_list.append(temp_list) # 记录符合要求的数据
return
if sum0 > target: # 和超过了目标
return
for i in range(pos, len(candidates)):
temp_list.append(candidates[i]) # 把第一个数放到列表
sum0 += candidates[i] # 求和
self.diguii(candidates, target, i, sum0, temp_list, ans_list) # 递归
sum0 -= candidates[i] # 减去上一个元素
temp_list.pop() # 去除列表最后一个元素
ans = Solution()
res = ans.combinationSum([2, 3, 6, 7], 7)
print(res)
思路没有错,但是得到的结果是
[[], []]
一开始以为是代码哪部分写错了,后面发现,python中列表的append方法是浅拷贝;我参考的方法使用的是c++中的容器vector,容器的方法都是深拷贝。由于我在最后使用了pop方法,所以得到的结果就只有空。
关于浅拷贝可以看一下这个或者自行百度。
https://zhuanlan.zhihu.com/p/161266559
在python中可以使用copy模块中的deepcopy函数进行深拷贝。
import copy
ls = [1, 2]
print(id(ls)) # 列表的地址
a = []
a.append(ls)
print(id(a[0])) # 第一个元素的地址,与列表ls的地址相同
b = copy.deepcopy(ls)
print(id(b)) # 深拷贝之后地址不同
修改一下之前的代码,把浅拷贝改成深拷贝。
import copy
class Solution:
def combinationSum(self, candidates, target):
ans_list = [] # 求解的答案
ls = [] # 临时用的列表
self.diguii(candidates=candidates, target=target, pos=0, sum0=0, temp_list=ls, ans_list=ans_list)
return ans_list
def diguii(self, candidates, target, pos, sum0, temp_list, ans_list): # pos 是遍历位置, sum是当前的和, temp是列表
if sum0 == target: # 数据和等于目标值
##################修改了这里####################
temp_deepcopy = copy.deepcopy(temp_list) # 深拷贝
ans_list.append(temp_deepcopy)
return
if sum0 > target: # 和超过了目标
return
for i in range(pos, len(candidates)):
temp_list.append(candidates[i]) # 把第一个数放到列表
sum0 += candidates[i] # 求和
self.diguii(candidates, target, i, sum0, temp_list, ans_list) # 递归
sum0 -= candidates[i] # 减去上一个元素
temp_list.pop() # 去除列表最后一个元素
ans = Solution()
res = ans.combinationSum([2, 3, 6, 7], 7)
print(res)
运行结果:
[[2, 2, 3], [7]]