我真的是个人才,但MMP,python太慢了!
我看这个第一遍:暴力搜索!
ok,复杂度O(N^2),不和你闹,我换招。
然后我就写了9的连续子序列和,我靠?我好像发现了什么。
首先如果子序列长度是1:那么这些和是{1,2,3...9}
如果子序列长度是2:{3,5,7,...17}
以此类推,我们发现这些数字的集合中,9出现的次数便是答案。
但是如果首项大于9了,比如序列长为4:{10,14,...}
那么直接跳过剩余的就好。
我发现高中数学的用处了,那些集合的序列都是等差的!!!
而且规律是如果子序列长度为K,那么首项S1=SUM(1~k)。
并且如果(N-S1)mod k==0,那么说明N处在这个序列中,因为是单调递增,所以只能出现一次,计数器加一。
我们把这个思路写成python代码:
class Solution(object):
def consecutiveNumbersSum(self, N):
"""
:type N: int
:rtype: int
"""
if N<=2:
return 1
c=0
for x in range(1,N):
s=x*(x+1)//2
if s<N:
if (N-s)%x==0:
c+=1
elif s==N:
c+=1
break
else:
break
return c
好的,没啥毛病,几十万的N也就一瞬间的时,但是我超时?
我:???,连O(n)都不到的 算法几乎是最佳算法了,而且我还用了求和公式(s=首项加末项乘以项数除以二),
用常数操作代替O(k)的求和了啊。
我决定百度一下看看还有哪位高人用了更快的方法。
后来我发现,大家思路大同小异。
于是我换了java来提交:
class Solution {
public int consecutiveNumbersSum(int N) {
if(N<=2)
return 1;
int c=0;
for(int i=1;i<N;++i){
int s=i*(i+1)/2;
if(s>N){
break;
}
else if(s==N){
c++;
break;
}
else{
if((N-s)%i==0)
c++;
}
}
return c;
}
}
好的,我仅仅是把py代码翻译了一下,一瞬间就过了。
这真的不是我的锅。