我想找出给定范围内几个数字的前k个数字的总和是否等于最后k个数字的总和。这里的范围非常大,k小于20。
我们可以通过强力方法实现这一目标。有人可以建议一些其他有效的算法。同样的?
答案 0 :(得分:1)
如果是一个范围,第一个数字不会经常改变,最后一个数字会以简单的方式改变。 S是前20位的总和。虽然secund数字不会改变,但当你转到下一个数字时,总和将增加1。因此,除了最后一个数字之外的所有数字都是固定的,如果最后一个数字等于i的总和是Si,那么唯一好的最后一个数字是n = S - Si + i。然后,您必须检查n是否介于0和9之间,以及结果数是否在区间内。这减少了十次查找次数。
您可以检查下一个较低的数字 如果第一个n小于0,则需要将secund数字减少-n。拨打n2这个secund数字。如果n2> = 0,好的数字将以(n2,0),(n2 -1,1),...,(0,n2)结束。这使复杂性降低了100。 如果n大于10,则将第二个数字增加n-9。将n2称为第二位数字。如果n2 <= 9,则好的数字是(n2,9),(n2-1,8),......,(0,某事物)。 这也使复杂性降低了100。
您可以对第三个数字执行相同操作,然后对第四个数字执行相同操作,直到20个。这将导致仅1个总和,以及O(解决方案数量)的复杂性,因此它是最小的。对于编码,请注意您的第一个数字可能会发生变化。每组20个第一个数字进行一次计算。
答案 1 :(得分:0)
对蛮力方法的一个理论上的改进:
1)总结第k个数字,存储在sumFirst
中
2)总结最后的k个数字,但如果总和超过sumFirst
则停止。
第2点可以节省一些最后几位的数字。
但你必须衡量额外的逻辑,花费更多,然后简单地添加所有k个数字。
答案 2 :(得分:0)
对蛮力的另一个改进:
i = 0, T = 0
while |T| < 9 * (k - i)
T = T + last[i] - first[i]
i = i + 1
return T == 0
答案 3 :(得分:0)
优化N-k
改进算法的一种方法是,当具有N位数的数字具有以下属性时:
N < 2k
。
例如,如果N = 5且k = 3,5 < 2x3
,则数字为
abcde
您只需要ab
对de
进行计数(即无需检查k
(3)位,因为3 rd 由k共享-last和k-first digits。)换句话说,双方计数的位数仅为
min(k, N-k), having N >= k
答案 4 :(得分:0)
如果要对同一个数组多次使用,可以将所有元素与前面的元素相加,O(n)
数组的大小为n
,即
for(int i = 1; i < n; i++)
arr[i] = arr[i] + arr[i-1];
这会将您的数组从probability density function转换为cumulative distribution function(对于离散数字)。因此,您的查询将是O(1)
,即
if(arr[k-1] == (arr[n-1]-arr[n-k])) //arr[k-1] is sum of first k element
return true;
return false;