劍指Offer——和爲S的連續正數序列

題目描述

小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。但是他並不滿足於此,他在想究竟有多少種連續的正數序列的和爲100(至少包括兩個數)。沒多久,他就得到另一組連續正數和爲100的序列:18,19,20,21,22。現在把問題交給你,你能不能也很快的找出所有和爲S的連續正數序列? Good Luck!

輸出描述

輸出所有和爲S的連續正數序列。序列內按照從小至大的順序,序列間按照開始數字從小到大的順序

輸入輸出舉例:輸入sum=15時,輸入應包含1-5、4-6、7-8三個連續序列。

方法一

維護一個二維vector:vector< vector<int> > record,res[i][j]表示從序列i到j的和,如果和爲sum則把i-j的連續序列放入放回結果中。

代碼如下:

class Solution {
public:
    vector< vector<int> > FindContinuousSequence(int sum) {
        vector< vector<int> > res;
        if( sum <= 0 )
            return res;
        int size = sum;
        vector< vector<int> > record(size, vector<int>(size,-1));
        for( int i=0;i<size;i++ )
        {
            for( int j=0;j<size;j++ )
            {
                if( i==0 || i>=j )
                    continue;
                if( j == i+1 )
                    record[i][j] = i+j;
                else
                    record[i][j] = record[i][j-1] + j;
                if( record[i][j] == sum )
                {
                    vector<int> temp;
                    for( int k=i;k<=j;k++ )
                        temp.push_back(k);
                    res.push_back(temp);
                }
            }
        }
        return res;
    }
};

缺點:空間複雜度大,且計算過程中其實有很多重複的地方,如計算1-5、2-6時,其實中間2-5的和計算了兩次,進行了不必要的計算,所以提出以下改進

方法二

前面已經說過,其實計算1-5的和與計算2-6的和,中間2-5的部分是重複的,可以直接利用,而不是重新計算。

考慮用small和big分別表示連續序列的開始和結尾數字,首先令small=1,big=2,計算從samll到big的連續序列的和temp_sum

  • 如果temp_sum < sum,則令big++,temp_sum += big;
  • 如果temp_sum > sum,則令temp_sum -= small,small++;
  • 如果temp_sum = sum,則將當前small-big的連續序列存入結果中。然後令big++,temp_sum += big,重複上述兩個過程來尋找其他符合條件的連續序列;
  • 結束條件:由於需要連續的至少兩個數,所以small需要小於big,因此當small大於等於big時,停止上述過程。

代碼如下

class Solution {
public:
    vector< vector<int> > FindContinuousSequence(int sum) {
        vector< vector<int> > res;
        if( sum <= 0 )
            return res;
        
        int small = 1;
        int big = 2;
        int temp_sum = small + big;
        while( small < big )
        {
            if( temp_sum == sum )
            {
                vector<int> temp;
                for( int i=small;i<=big;i++ )
                    temp.push_back(i);
                res.push_back(temp);
                // 這裏不要忘了
                big++; 
                temp_sum += big;
            }
            else if( temp_sum < sum )
            {
                big++;
                temp_sum += big;
            }
            else
            {
                temp_sum -= small;
                small++;
            }
        }
        return res;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章