我正在尝试Bonetrousle HackerRank challenge.
问题如下:
在K以下找到B个不同的正整数,使它们的和为N或说不可能。
约束:
n, k <= 10^18
b <= 10^5
如果给定的N位于最小(取前B个元素)和最大(取后B个元素)和之间,则可以检查是否存在解决方案。 从那开始,我从最小的总和开始,然后通过在不破坏约束的情况下为每个元素分配最大可能的值来使其达到N。 (无重复,总和== N)
下面是我写的代码。
def foo1(n,k,b):
minSum = (b*(b+1))//2
maxSum = (b)*(k-b+1+k)//2
#maxSum = (k*(k+1))//2 - minSum
#print(minSum, maxSum)
if n>=minSum and n<=maxSum:
minArr = [i for i in range(1,b+1)]
minArr.reverse()
sumA = sum(minArr)
maxA = k
for i in range(len(minArr)):
tmp = minArr[i]
minArr[i] = maxA
sumA = sumA-tmp+minArr[i]
while sumA > n:
sumA -=1
minArr[i] -= 1
maxA = minArr[i]-1
"""
while sumA+1 <= n and minArr[i]+1 <= k and minArr[i]+1 != maxA:
#print(minArr, maxA)
minArr[i]+=1
sumA +=1
maxA = minArr[i]
if sumA == n:
break
"""
else:
return [-1]
return minArr
代码输出正确的解决方案,但是在4个测试用例的黑客级别上超时。 (样本n,b,k:19999651,20000000,6324) 对于相同的测试用例,它可以在我的机器上3秒钟内给出答案。
最初,我认为问题出在注释代码上,因为我试图逐个递增每个元素数组直到达到总和。我修改了代码,为每个元素分配了最大可能的值,然后在违反约束的情况下将其递减,但是显然并没有太大帮助。
关于修改代码以使其通过时序约束或更快算法的任何建议?
答案 0 :(得分:3)
首先,找到总和为<= N 的 B 个最大的连续整数。如果此序列以整数<1或整数> K
结尾,则不可能出现问题以 x 开头的 B 整数之和为 B *(2x + B-1)/ 2 ,因此只需解决< strong> x 直接。
很明显,如果您要在以 x 开头的序列中的每个整数中加一个,那么您将得到 next B 个连续的整数,它们的总和为 N ,因此您不需要增加那么多。只需在序列中的最高 N-sum 个整数中加1,就可以得出正确的和。