题目描述
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
输入:100
输出:[[9,10,11,12,13,14,15,16],[18,19,20,21,22]]
算法思路
NAIVE
第一个想到的方法是做一个字典,保存每个数的前n项和。
然后用双指针i,j遍历字典,将所有d[j]-d[i]==target的从i到j的连续数列保存到结果中。
这个双指针也可以当作滑动窗口来着没差啦。
class Solution:
def findContinuousSequence(self, target: int):
n,di,res=0,{0:0},[]
for i in range(1,target//2+2):
n+=i
di[i]=n
i,j=0,1
while j<=target//2+1:
v=di[j]-di[i]
if v==target:
ls=list(range(i+1,j+1))
res+=[ls]
j+=1
if v>target:i+=1
elif v<target:j+=1
return res
执行用时 :188 ms, 在所有 Python3 提交中击败了63.02%的用户
内存消耗 :21.1 MB, 在所有 Python3 提交中击败了100.00%的用户
拓展
采用求和公式替代了字典,结果内存消耗显著减少,但是耗时显著增长。
考虑应该是用求和公式在While循环中出现了大量重复计算。
class Solution:
def findContinuousSequence(self, target: int):
n,res,i,j=0,[],0,1
def SUM(n):return n*(n+1)/2
while j<=target//2+1:
v=SUM(j)-SUM(i)
if v==target:
res.append(list(range(i+1,j+1)))
j+=1
if v>target:i+=1
elif v<target:j+=1
return res
执行用时 :340 ms, 在所有 Python3 提交中击败了34.47%的用户
内存消耗 :13.4 MB, 在所有 Python3 提交中击败了100.00%的用户
然后添加字典,一边使用求和公式一边记录所有求过的和。
结果反向喜人。
耗时没咋变化,空间复杂度回到了最开始的水平。
幽灵飘。
class Solution:
def findContinuousSequence(self, target: int):
n,res,i,j,d=0,[],0,1,{}
def SUM(n):return n*(n+1)/2
while j<=target//2+1:
v=d.setdefault(j,SUM(j))-d.setdefault(i,SUM(i))
if v==target:
res.append(list(range(i+1,j+1)))
j+=1
if v>target:i+=1
elif v<target:j+=1
return res
执行用时 :424 ms, 在所有 Python3 提交中击败了28.55%的用户
内存消耗 :21.1 MB, 在所有 Python3 提交中击败了100.00%的用户
IMPROVE
评论区还是多大佬啊,一看果然有好用的数学方法。
依然是求和公式:(首项+末项)*数列长度/2
- 由
(n+1)*n/2==target ——>n=int((2*target)**(0.5))
得到最长的数列长度 - 剪枝:所有数列长度都要满足条件
(target*2) % len == 0
- 根据数学公式可以得到beg=((2*target)/len-len+1)/2;且beg必须是整数
如此,易得算法:
class Solution:
def findContinuousSequence(self, target: int) -> List[List[int]]:
res=[]
for i in range(int((2*target)**(0.5)),1,-1):
if (target*2) % i == 0:
beg=((2*target)/i-i+1)/2
if beg==int(beg):
beg=int(beg)
res.append(list(range(beg,beg+i)))
return res
执行用时 :32 ms, 在所有 Python3 提交中击败了99.46%的用户
内存消耗 :13.3 MB, 在所有 Python3 提交中击败了100.00%的用户
妈耶 我到底是在写算法题还是数学题呢?沉思。