我需要一个带两个整数的函数,比方说n和m,其中n> = 0且m> = 1,它返回一个列表列表,包含将n分成m正的所有可能方法整数件(订单事项,[4,7,2]与[7,4,2]不同。)
现在,我能够提出一个快速的小递归函数来完成这项工作,如下所示:
def split(number, elements):
if elements == 1:
return [[number]]
ways = []
for i in range(0, number + 1):
for j in split_number(number - i, elements - 1):
values.append([i] + j)
return values
但是,我可能会使用大数字,因此需要将其转换为迭代方法。我不确定如何做到这一点,因为它每次'超级调用'会多次调用自己,这使得甚至很难转换为尾调用和累加器,更不用说它们转换为迭代形式了。
示例输出:
split(7, 2) -> [[0, 7], [1, 6], [2, 5], [3, 4], [4, 3], [5, 2], [6, 1], [7, 0]]
split(4, 3) -> [[0, 0, 4], [0, 1, 3], [0, 2, 2], [0, 3, 1], [0, 4, 0], [1, 0, 3],
[1, 1, 2], [1, 2, 1], [1, 3, 0], [2, 0, 2], [2, 1, 1], [2, 2, 0], [3, 0, 1], [3, 1, 0],
[4, 0, 0]]
等
答案 0 :(得分:0)
这是使用itertools的方法:
def chainsplit(n,p):
return sorted(list(set(chain.from_iterable([list(permutations(i,len(i)))
for i in list(combinations_with_replacement(range(n+1),p)) if sum(i) == n]))))
以下是一些时间基准,显示了列表转换,排序和函数调用的开销:
%timeit set(chain.from_iterable([list(permutations(i,len(i))) for i in list(combinations_with_replacement(range(5),3)) if sum(i) == 4]))
10000 loops, best of 3: 20 µs per loop
%timeit list(set(chain.from_iterable([list(permutations(i,len(i))) for i in list(combinations_with_replacement(range(5),3)) if sum(i) == 4])))
10000 loops, best of 3: 20.4 µs per loop
%timeit sorted(list(set(chain.from_iterable([list(permutations(i,len(i))) for i in list(combinations_with_replacement(range(5),3)) if sum(i) == 4]))))
10000 loops, best of 3: 25 µs per loop
%timeit chainsplit(4,3)
10000 loops, best of 3: 26.4 µs per loop
以下是@ zyxue&n;基于numpy的函数f()的基准测试用于比较:
timeit f(4,3)
10000 loops, best of 3: 133 µs per loop
运行你的split()函数会冻结我的内核,所以我无法计时。请注意,在其中split_function应更改为拆分或将函数名称更改为split_function以使其起作用。 split_function可能是更好的选择,以避免与名为split的其他函数混淆。
答案 1 :(得分:0)
import numpy as np
from itertools import combinations_with_replacement
def f(n, m):
r = combinations_with_replacement(xrange(n + 1), m - 1)
return [np.diff([0] + list(x) + [n]).tolist() for x in r]
assert f(7, 2) == [[0, 7], [1, 6], [2, 5], [3, 4], [4, 3], [5, 2], [6, 1], [7, 0]]
assert f(4, 3) == [[0, 0, 4], [0, 1, 3], [0, 2, 2], [0, 3, 1], [0, 4, 0], [1, 0, 3],
[1, 1, 2], [1, 2, 1], [1, 3, 0], [2, 0, 2], [2, 1, 1], [2, 2, 0],
[3, 0, 1], [3, 1, 0], [4, 0, 0]]
答案 2 :(得分:0)
维护一系列未完成的工作。
未完成的作业是一个数字列表,其中第一个元素可能会进一步分割。从队列中提取作业,以可能的方式拆分第一个元素,然后将生成的作业添加回队列。
算法如下(折衷伪代码)
compositeId
答案 3 :(得分:0)
这是Python中的递归转向迭代方法:
def f(n,m):
stack = [([n] + (m - 1)*[0],0)]
result = []
while len(stack) > 0:
(p,i) = stack.pop()
if i == m - 1:
result.append(p)
else:
for k in xrange(0,p[i] + 1):
_p = p[:]
_p[i] = _p[i] - k
_p[i + 1] = p[i + 1] + k
stack.append((_p,i + 1))
return result
print(f(4,3))
print(f(7,2))