Findall possible combinations of k numbers that add up to a number n,given that only numbers from 1 to 9 can be used and each combination should bea unique set of numbers.
Example1:
Input: k =3, n = 7
Output:
[[1,2,4]]
Example2:
Input: k =3, n = 9
Output:
[[1,2,6], [1,3,5], [2,3,4]]
这一题我是使用BFS做的,最后打败了87%的提交
首先这一题可以使用DFS做,但是使用DFS的话函数栈会占用很多额外的空间,耗费更多的时间,用迭代的形式使用BFS做会更快
这一题有非常多的可以剪枝的地方
首先对于某个k和n而言,
当if n < 45 -theCount[k + 1] or n > theCount[9 - k + 1]:的时候,说明这个时候n大于当前k个元素可以取得的最大值或者是最小值,比如当k为3的时候,可以取得的最小值是1 + 2 + 3 = 6,可以取的的最大值是7 + 8 + 9 =24,这个时候可以直接return
使用一个栈来theDp存储已经取得的数(使用的并不是Dp),当theDp中的最后一个数是i的时候,下一个数可以在i + 1 ~ 9的范围取,当剩下的数的个数也就是9 – i – 1 +1不足以凑够k个数的时候,可以剪枝,
当剩下所有数的和也就是(i+ 1) +( i+ 2) +( i + 3)…+9和sum(Dp)相加小于n的时候,说明剩下的数全部加起来在加上theDp里面的数都不能到达n,这个时候也可以剪枝,
当theDp中的数的个数>= k的时候,说明已经取了k个数,没有必要往下取,可以剪枝
通过这一题我学会了,python里面,数组赋值并不是复制,而是把地址进行传递,要想复制值得用extend,类的对象的声明使用aa = solution()(这一点和C++一样)
class Solution(object):
def combinationSum3(self, k, n):
"""
:type k: int
:type n: int
:rtype: List[List[int]]
"""
theCount = [0 for i in range(11)]
for i in range(9, 0, -1):
theCount[i] = i + theCount[i + 1]
result = []
if k > 9 or k <= 0:
return result
if n < 45 - theCount[k + 1] or n > theCount[9 - k + 1]:
return result
theDp = [[i] for i in range(1, 10)]
while len(theDp):
tmp = theDp.pop(0)
if len(tmp) == k:
if sum(tmp) == n:
result.append(tmp)
continue
theKNeed = k - len(tmp)
for i in range(tmp[-1] + 1, 10):
if 9 - i + 1 >= theKNeed and sum(tmp) + theCount[i] >= n:
tmp2 = []
tmp2.extend(tmp)
tmp2.append(i)
theDp.append(tmp2)
return result