今天,在练习一些算法问题时,我发现了一个有趣的问题。 问题是
你必须将1除以
Form
(一个缺失值n
)为两等 这两半的总和相等的一半。示例:
如果
x
和n = 7
解决方案将是
x = 4
和{7, 5}
我可以用蛮力方法回答它,但我想要一个有效的解决方案 任何人都可以帮助我吗?
答案 0 :(得分:0)
如果没有x的元素1→N的总和是奇数,那么就没有解。
否则,您可以在O(N)中找到平衡选择的解决方案。
首先让我们考虑四个连续数字的任何序列可以分成两组,并给出相等的总和:
[x,x + 1,x + 2,x + 3]→[x + 3,x]; [x + 2,x + 1]
因此选择它们并将它们放入集合中A B B A平衡集合A和B.
此外,当我们在省略的值上有两对夫妻时,它可以拥有类似的属性:
[x-2,x-1,x + 1,x + 2]→[x + 2,x-2]; [x + 1,x-1]
所以仍然是A B B A
此时我们可以解决以下问题:
好吧,但可能会发生我们有3个数字,x和其他3个数字或其他条件。我们怎么能以平衡的方式选择呢?
如果我们再看一下x:
之间的差距[x-1,x + 1]
我们可以注意到,如果我们将两个邻居分成两个独立的集合,我们必须平衡集合上的+2和更大的总和。
我们可以使用序列的最后四个数字来完成此操作:
[4 3 2 1]→[4,2]; [3,1]→6; 4
最后我们必须考虑到我们可能没有其中一个,所以让我们构建另一个案例:
[3 2 1]→[2]; [3,1]→2; 4
让我们也意识到我们可以在A B A B(或B A B A)模式的序列的另一端做同样的事情 - 如果我们的+2代表B(或A);
令人惊讶的是,如果我们跳h(奇数!)数字仍然有4个:
[x + 3,x + 2,x-2,x-3]→[x + 3,x-3]; [x + 2,x-2]
因此,探索数组我们可以逐步绘制解决方案
一个例子:
11 10 9 8 7 6 5 4 3 2 1
它的总和是偶数,因此x只能是偶数:
x = 10
11 - 9 | 8 7 6 5 | 4 3 2 1 → (+2 gap - on A) (4 in a row) (balancing tail)
A B A B B A B A B A
x = 8
11 10 | 9 - 7 | 6 5 | 4 3 2 1 → (4 across +) (+2 gap - on A) (balancing tail)
a b A B | b a | B A B A
x = 6
11 10 9 8 | 7 - 5 | 4 3 2 1 → (4 in a row) (+2 gap - on A) (balancing tail)
A B B A A B A B B B
x = 4 we have no balancing tail - we have to do that with head
11 10 9 8 | 7 6 | 5 - 3 | 2 1 → (balancing head) (4 across +) (+2 gap)
A B A B A B | b a | B A
x = 2
11 10 9 8 | 7 6 5 4 | 3 - 1 → (balancing head) (4 in a row) (+2 gap)
A B A B A B B A B A
有趣的是注意到解决方案的对称性。另一个例子。
10 9 8 7 6 5 4 3 2 1
它是奇数的总和,所以x只能是一个奇数,现在元素的数量是奇数。
x = 9
10 - 8 | 7 6 5 4 | 3 2 1 → (+2 gap - on A) (4 in a row) (balancing tail)
A B A B B A B A B
x = 7
10 9 | 8 - 6 | 5 4 | 3 2 1 → (4 across +) (+2 gap - on A) (balancing tail)
a b | A B | b a B A B
x = 5
10 9 8 7 | 6 - 4 | 3 2 1 → (4 in a row) (+2 gap - on A) (balancing tail)
A B B A A B B A B
x = 3
10 9 8 7 | 6 5 | 4 - 2 | 1 → (balancing head) (4 across + virtual 0) (+2 gap)
A B A B B A | a b | A
x = 1
10 9 8 7 | 6 5 4 3 | 2 → (balancing head) (4 in a row) (+2 gap virtual 0)
A B A B A B B A B
最后值得注意的是,只要我们有一个完整的平衡段(即 4连续或4对),我们就可以从A切换到B.
搞笑说 - 但要求总和([1 ... N] -x)的财产是平均的,如果你自己尝试就会使案件多余。
我很确定这个算法可以推广 - 我很快就会提供一个修订版本。
答案 1 :(得分:0)
通过使用预处理步骤包装标准subset sum problem动态编程,可以解决此问题。这些步骤是O(1)com
算法(n,x):
if(neededSum%2!= 0):return 0
创建数组[1..n]并从中删除x
子集算法的工作python实现 - 打印所有子集如下。
def subsetsum(arr, i, sum, ss):
if i >= len(arr):
if sum == 0:
print ss
return 1
else:
return 0
ss1 = ss[:]
count = subsetsum(arr, i + 1, sum, ss1)
ss1.append(arr[i])
count += subsetsum(arr, i + 1, sum - arr[i], ss1)
return count
arr = [1, 2, 3, 10, 5, 7]
sum = 14
a = []
print subsetsum(arr, 0, sum, a)
希望它有所帮助!