/*
思路1:
1)由于我们要找的是和为S的连续正数序列,因此这个序列是个公差为1的等差数列,而这个序列的中间值代表了平均值的大小。
假设序列长度为n,那么这个序列的中间值可以通过(S / n)得到,知道序列的中间值和长度,也就不难求出这段序列了。
2)满足条件的n分两种情况:
n为奇数时,序列中间的数正好是序列的平均值,所以条件为:(n & 1) == 1 && sum % n == 0;
n为偶数时,序列中间两个数的平均值是序列的平均值,而这个平均值的小数部分为0.5,所以条件为:(sum % n) * 2 == n.
3)体面要求序列间按照开始数字从小到大的顺序,而n越大开始数字自然越小,所以从最大n依次递减。假定从1开始加求得超过
100对应的n值,由等差数列公示S=(1+n)*n/2,n=sqrt(2*s)
*/
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > res;
for(int n=sqrt(2*sum);n>=2;n--){
if(((n&1)==1 && sum%n==0) || (sum%n)*2==n){
vector<int> temp;
for(int i=0;i<n;i++){
temp.push_back((sum / n) - (n - 1) / 2 + i);
}
res.push_back(temp);
}
}
return res;
}
};
/*
思路2:
双指针问题
利用高低两个指针,当前总和小于sum时大指针++;
总和小于sum时小指正++;直到相等时输出数组,大指针++。
该方案思路明确,需要一些无用的循环,比思路1的空间复杂度要高。
*/
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > res;
int pl = 1,ph = 2;
while(pl<ph){
int curSum = (pl + ph) * (ph - pl + 1) / 2;
if(curSum < sum)
ph++;
if(curSum == sum){
vector<int> temp;
for(int i=pl;i<=ph;i++){
temp.push_back(i);
}
res.push_back(temp);
ph++;
}
if(curSum > sum)
pl++;
}
return res;
}
};