这是"given sum problem"的变体,我尝试在 Python 中编写一个解决方案,它将在O(log n)
时间内解决它。对于给定的自然数N
(equal or larger than 1)
,找到最短的项目p
1..n
,其总和为N
,{ {1}}项是迭代下面的产品:
p
p
的值为i
p
i-1
或{{1 }} <子> * 2
子> p
从i-1
+ 1
开始,正好是1
因此:
p
1
始终为2,但p
2
可以是3或4
对于输入p
,候选集是:[1,2,4,5,6],[1,2,3,4,8],[1,2,4,5,6] ],[1,2,3,4,8]
3
。
这是我到目前为止所编写的代码,但它很慢并且在适度的&#34;大&#34; (N> = 1000)值:
N = 18
如何以更有效的方式解决它?
最快的解决方案是最重要的,但也可以使用更多的 pythonic 代码。
答案 0 :(得分:2)
使用广度优先搜索来减少浪费的精力。下面的代码可以进行更多优化。
def solution(n):
q = [(1,)]
visited = set()
for seq in q:
s = sum(seq)
if s == n:
return seq
elif s > n:
continue
key = (seq[-1], s)
if key in visited:
continue
visited.add(key)
q.append(seq + (seq[-1] * 2,))
q.append(seq + (seq[-1] + 1,))
return None
答案 1 :(得分:1)
您正在寻找最短的解决方案,因此如果您找到了解决方案,则无需寻找更长的解决方案。
您可以更改代码,这样它就不会找到比您通过这种方式找到的解决方案更长的解决方案:
(注意添加的if条件)
def tea(n, l, target):
global possible
if (sum(l) > target):
return
elif (sum(l) == target):
possible.append(l)
# we want to keep looking for new solutions only if l is shorter!
if possible and (len(l) >= max(len(i) for i in possible)):
return
i = n * 2
tea(i, l + [i], target)
i = n + 1
tea(i, l + [i], target)
此外,似乎您希望函数在没有解决方案时返回-1
,目前,您的代码会在这种情况下引发错误,我会将solution()
函数更改为:< / p>
possible = []
def solution(N):
global possible
tea(1, [1], N)
sizes = [len(p) for p in possible] # you can use: size = map(len,possible) instead
if sizes:
return min(sizes)
return -1
至于你的“更多 pythonic 代码”,我会这样写:
def solution(N):
possibles =[]
tea(1, [1], N, possibles)
if not possibles:
return -1
else:
return min(map(len,possibles))
def tea(n, l, target, possibles): # maybe a better name then "tea"
if (sum(l) > target):
return
elif (sum(l) == target):
possibles.append(l)
return
if possibles and (len(l) >= max(len(i) for i in possibles)):
return
tea(n * 2, l + [n * 2], target, possibles)
tea(n + 1, l + [n + 1], target, possibles)