题解 | #和为S的连续正数序列#

和为S的连续正数序列

http://www.nowcoder.com/practice/c451a3fd84b64cb19485dad758a55ebe

先用暴力法解。
用一个二重循环遍历1~sum/2+1中的数。
外层循环控制该连续序列的起点,内层循环用于记录该序列以及该序列的和。
当序列和等于sum时,将当前序列加入结果集,退出内层循环。当序列和大于sum时,直接退出内层循环。
这样做时间复杂度在O(n^2),空间复杂度为O(n)。

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        vector<vector<int>> res;
        if(!sum){
            return res;
        }
        for(int i = 1;i < sum / 2 + 1;i++){
            int count = 0;
            vector<int> temp;
            for(int j = i;j < sum / 2 + 2;j++){
                count += j;
                temp.push_back(j);
                if(count == sum){
                    res.push_back(temp);
                    break;
                }
                if(count > sum){
                    break;
                }
            }
        }
        return res;
    }
};


更好的方法是用滑动窗口的方法来做。
用两个指针来标记窗口的边界,每次计算窗口内数字的和,当和大于sum时,窗口左边界右移,当和小于sum时,窗口右边界右移。
由于连续序列的定义要求最少要两个数字,所以终止条件为窗口的右边界超过sum/2+1。
这个算法最巧妙的地方在于计算窗口中的和时,不需要累加,而直接用等差数列求和公式即可。

时间复杂度为O(n),空间复杂度为O(n)。

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        vector<vector<int>> res;
        if(!sum){
            return res;
        }
        int left = 1;
        int right = 2;
        while(right < sum / 2 + 2){
            int count = (left + right) * (right - left + 1) / 2;
            if(count > sum){
                left++;
            }
            else if(count < sum){
                right++;
            }
            else{
                vector<int> temp;
                for(int i = left;i < right + 1;i++){
                    temp.push_back(i);
                }
                res.push_back(temp);
                right++;
            }
        }
        return res;
    }
};
全部评论

相关推荐

评论
点赞
收藏
分享
牛客网
牛客企业服务