1.滑动窗口
因为结果是连续序列,所以可用头哨兵尾哨兵来唯一确定一个序列。序列的和也可以计算出。因此有n*n个序列需要去判断。
但是当知道了某序列的值已经比target要大,则相同起点更长的序列不需要判断,所以可以剪枝掉一部分,因此有滑动窗口一说。
具体流程:
序列初始为[1]其值为1(如果是0会错)。
小于target时头走一步(可根据增量来计算出新序列的值)
大于target时尾走一步
相等时记录(两者任意走一步即可)
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
//record
vector<vector<int>> result;
int sum = 1;
//boundary
int l = 1;
int r = 1;
int sidx = 1;
int eidx = target/ 2 + 1;
//main
while (l <= r && r <= eidx){
if (sum == target){
//cout<<1<<endl;
vector<int> tmp_vec;
for(int i = l; i <= r; i++)
tmp_vec.push_back(i);
result.push_back(tmp_vec);
sum -= l++;
sum += ++r;
} else if (sum < target){
//cout<<2<<endl;
sum += ++r;
} else if (sum > target){
//cout<<3<<endl;
sum -= l++;
}
}
return result;
}
};
2.计算
因为所求为连续序列,可以设序列中位数为x,数量为n,则target=n*x
奇数序列时,中位数就是序列中间的数
偶数序列时,中位数就是序列中间两个数的平均值,可以认定是两者中较小的数字+0.5
(tips:当target翻倍时,中位数是整数)
所以在某个确定的长度n下,可以通过计算算出是否有序列存在。
而n的边界的话,因为初始化序列为[1],则n应该从1开始增加,最大值为可能出现的最长的序列。
最长的序列应该是从1开始到x,其值为(x+1)*x/2
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
//record
vector<vector<int>> result;
int n = 1;
//boundary
int limit = sqrt(target*2) + 1;
//main
while ( ++n <= limit ){
if( (n%2==1 && target%n==0) ||
(n%2==0 && target%n!=0 && target*2%n==0) ){ //奇数列 中位数是整数 偶数列 中位数是0.5小数
int mid = target / n;
vector<int> tmp_vec;
if( n%2 == 1 ){ //奇数序列
for (int i = mid - (n-1)/2; i <= mid + (n-1)/2 ;i++)
tmp_vec.push_back(i);
}else {
for (int i = mid - (n-1)/2; i <= mid + (n-1)/2 + 1 ;i++)
tmp_vec.push_back(i);
}
if(tmp_vec[0] != 0)
result.push_back(tmp_vec);
}
}
reverse(result.begin(), result.end());
return result;
}
};