滑动窗口的解法的时间复杂度很显然是
O
(
N
)
O(N)
O(N),实际时间复杂的可以常数降低至
O
(
N
2
)
O(\frac{N}{2})
O(2N)
前缀的话,一遍求前缀数组,然后按照滑动窗口的方式。其实最终都是滑动窗口的思维方式,因为
O
(
N
2
)
O(N^2)
O(N2) 枚举起终点的解法太垃圾了
还有一种官方没有的解法,时间复杂度可以降低至
O
(
N
)
O(\sqrt{N})
O(N):
如果长度为
n
n
n 的连续整数和为
s
u
m
sum
sum,那么
s
u
m
n
\frac{sum}{n}
nsum 就是中位数。知道中位数和长度,就可以得到整个序列了
可以对
n
n
n 进行分类讨论:
n
是
奇
数
:
n是奇数:
n是奇数:序列中间数正好是
s
u
m
n
\frac{sum}{n}
nsum,开始元素为
s
u
m
n
−
(
n
−
1
2
)
\frac{sum}{n}-(\frac{n-1}{2})
nsum−(2n−1)。条件为:n % 2 == 1 && sum % n == 0;
n
是
偶
数
:
n是偶数:
n是偶数:序列偏左的中间数是
s
u
m
n
\frac{sum}{n}
nsum,开始元素同上。条件为:(sum%n) * 2 == n
那么n的范围是多少呢?最小肯定是2,最大的时候,我们就需要使整体和最小。那么久从1开始算起。根据等差数列和公式,得到条件:
(
1
+
n
)
∗
n
/
2
<
=
S
(1+n)*n/2<=S
(1+n)∗n/2<=S →
n
<
2
S
n<\sqrt{2S}
n<2S
注意到我们所取的
n
n
n 的范围:
[
2
,
2
S
]
[2, \sqrt{2S}]
[2,2S]
在这个范围内的
n
n
n是通过等差数列和公式推导出来的,也就是说,都是满足等差数列前n项和的n。推算条件的数列最小元素是1.所以,在这个条件下,肯定不会出现非正整数的情况。
AC-Code
O
(
N
)
解
法
O(N)解法
O(N)解法
classSolution{public:
vector<vector<int>>FindContinuousSequence(int sum){
vector<vector<int>> ans;int L =1, R =1;// [L. R] int num =1;while(L <= sum /2){if(num == sum){
vector<int> vec;for(int i = L; i <= R;++i)
vec.push_back(i);
ans.push_back(vec);
num -= L;++L;}elseif(num < sum){++R;
num += R;}else{
num -= L;++L;}}return ans;}};/* x-n,...,x,...,x+n
(2*n+1)*x==sum */
O
(
N
)
解
法
O(\sqrt{N})解法
O(N)解法
classSolution{public:
vector<vector<int>>FindContinuousSequence(int sum){
vector<vector<int>> ans;int n =sqrt(sum *2);for(int i = n; i >=2;--i){if(i &1&& sum % i ==0||(sum % i)*2== i){
vector<int> vec;for(int j =0, k =(sum / i)-(i -1)/2; j < i;++j,++k)
vec.push_back(k);
ans.push_back(vec);}}return ans;}};