给定一组N个正整数。设最小元素为L,所有元素之和为S.
我需要找出,对于每个整数X,(其中X在L和S之间),可以选择数组的子集,使得该子集中的元素总和等于X.
示例:
让N=5
和数组为{4,8,2,1,16}
。然后这里所有元素都可以在1到31之间进行,所以这里的答案是“是”。
如果假设N=4
且数组为{5,1,2,7}
。然后,对于1到15之间的值,不能进行值4和11。 所以这里的回答是“不”。
答案 0 :(得分:2)
我知道找到这个数组不能返回的最小数字,但不知道如何解决这个问题
首先,数组只有一个元素吗?如果是这样,答案是肯定的。
否则,找到最小的不可能总和。它比S大吗?如果是这样,答案是肯定的。否则,答案是否定的。 (如果最小值小于L,则数组不包含1,并且S-1是不可能的总和。)
要找到最低的不可能总和,我们对输入进行排序,然后找到数组每个前缀的最低不可能总和。在Python中:
def lowest_impossible_sum(nums):
nums = sorted(nums)
partial_sum = 0
for num in nums:
if num > partial_sum + 1:
return partial_sum + 1
partial_sum += num
return partial_sum + 1
通过归纳证明正确性:
设A为排序数组。如果A[0] > 1
,则1是最低的不可能总和。否则,A[:1]
的元素可以产生最多sum(A[:1])
的所有总和。
假设可以选择A[:k]
的子集来生成最多sum(A[:k])
的所有总和。
A[k] > sum(A[:k]) + 1
,则sum(A[:k]) + 1
是最低的不可能总和;它不能由A[:k]
的子集生成,添加不在A[:k]
中的元素也无济于事,因为它们太大了。A[k] <= sum(A[:k]) + 1
,那么A[:k+1]
的子集可以产生最多sum(A[:k+1])
的总和。诱导假设已经可以生成sum(A[:k])
的每个总和,并且可以通过选择sum(A[:k]) + 1
和{{1}的合适子集来生成sum(A[:k+1])
到A[k]
的总和。添加到剩下的内容。如果没有这样的索引,则让x成为A[:k]
或A[x] > sum(A[:x]) + 1
的第一个索引。通过归纳,每个总和可达len(A)
。但是,无论是因为x超出数组的末尾还是因为sum(A[:x])
,都不可能产生总和A[x] > sum(A[:x]) + 1
。因此,我们只需要搜索x并返回sum(A[:x]) + 1
。这就是算法的作用。
答案 1 :(得分:0)
首先对数组中的所有元素进行排序。如果你想从数组的元素中得到L和S之间的所有值,那么 L = 1 ,元素应该是2 ^ i的形式。并且最大元素可能不是2 ^ i形式,因为总和不需要是形式(2 ^ i - 1)。