![](/img/trans.png)
[英]Given an array of N integers, and an integer K, find the number of pairs of elements in the array whose sum is equal to K
[英]Find permutations of positive integers given sum and given number of elements
如何找到给定总和和给定元素数量的正整数的所有排列。
例如,
Input: sum = 4, number of elements = 2.
Output: (1,3), (3,1), (2,2)
我的想法是,因为我知道元素的数量是N
,所以我将创建 N arrays,每个从 1 到总和S-1
。 因此,对于示例,我将从两个 arrays、 [1,2,3]
和[1,2,3]
开始。 然后我将遍历每个数组,比如
output = []
for x in array1:
for y in array2:
if x+y == target:
output.append((x,y))
但我不知道如何为任何N
制作它,因为那将是可变数量的 for 循环。
现在我有了第二个想法,我认为这可行。
import numpy as np
from itertools import combinations
def find_permutations(S,N):
x = np.asarray([x+1 for x in range(S)]*N)
y = [seq for seq in combinations(x,N) if sum(seq)==S]
return list(dict.fromkeys(y)) # remove duplicates
find_permutations(4,2)
[(1, 3), (2, 2), (3, 1)]
但这非常慢,因为它首先创建一个非常长的数组并找到所有组合然后过滤。 像find_permutations(16,16)
这样的东西需要很长时间,但它显然只是[(1,1,...,1)]
。
这是一个递归解决方案,它将生成满足要求的元组。
def get_combinations(target, num_elements, combinations=None):
# Initialise an empty list
if combinations == None:
combinations = []
# Calculate the sum of the current list of numbers
combinations_sum = sum(combinations)
# Check if the target is reached -> No further recursion necessary
if (combinations_sum == target and len(combinations) == num_elements):
# Return this combination of numbers
yield tuple(combinations)
else:
# The combination of numbers doesn't yet total to target value
# Iterate over each number from 1 to the target value
for number in range(1, target + 1):
# Check that neither the target value nor number of elements will be exceeded
if (combinations_sum + number <= target
and len(combinations) < num_elements):
# Add the number to the list
new_combo = combinations + [number]
# Find all solutions for the list
for c in get_combinations(target, num_elements, new_combo):
yield c
样本 output:
[c for c in get_combinations(4, 2)]
> [(1, 3), (2, 2), (3, 1)]
这是一个较短的(编辑以涵盖边界情况k <= 1
):
def f(sum, k):
if k < 1:
return []
if k == 1:
return [(sum,)]
if k == 2:
return [(i,sum-i) for i in range(1, sum-k+2)]
return [tup[:-1] + ab for tup in f(sum, k-1) for ab in f(tup[-1], 2)]
测试output:
f(2, 0) # []
f(3, 1) # [(3,)]
f(4, 2) # [(1, 3), (2, 2), (3, 1)]
f(5, 3) # [(1, 1, 3), (1, 2, 2), (1, 3, 1), (2, 1, 2), (2, 2, 1), (3, 1, 1)]
该算法采用 k-1 的结果(即f(sum, k-1)
,递归地)并应用相同的 function 将所有最后元素分解为 2 元组(即f(tup[-1], 2)
,再次递归)。
时间比较: f(5, 3)
的 10.000 次重复:0.07 秒
对于get_combinations(5, 3)
:0.30 秒
对于find_permutations(5, 3)
:2.35 秒
至于速度,我认为这与斐波那契数列的情况类似,这种嵌套递归效率非常低,不会让你超出f(20, 10)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.