1. 程式人生 > >小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。現在把問題交給你,你能不能也很快的找出所有和為S的連續正數序列? Good Luck!

小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。現在把問題交給你,你能不能也很快的找出所有和為S的連續正數序列? Good Luck!

/*
思路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;
    }
};