 
					
						网站救助计划
						
						
						
				  1.为阅读体验,本站无任何广告,也无任何盈利方法,站长一直在用爱发电,现濒临倒闭,希望有能力的同学能帮忙分担服务器成本
2.捐助10元及以上同学,可添加站长微信lurenzhang888,备注捐助,网站倒闭后可联系站长领取本站pdf内容
3.若网站能存活下来,后续将会持续更新内容
题目描述
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]示例 2:
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]限制:
- 1 <= target <= 10^5
题解 1
(双指针算法) O(n)
最容易想到的是用两重循环去枚举和为 S 的序列,时间复杂度是 O(n^2) 我们可以使用双指针算法进行优化,用两个指针 i, j 指向当前正在枚举的序列的起点和终点
- 当 i \sim j 之间的和小于 S 时, j 指针往后移
- 当 i \sim j 之间的和等于 S 时,记录当前序列,加入到答案中
- 当 i \sim j 之间的和大于 S 时,i 指针往后移
可以 i 和 j 是单调的,不会走回头路,且当 i 往后移时 j 不会往前移
时间复杂度
i 和 j 最终都从 1 走到 target,时间复杂度为 O(n)
空间复杂度
O(n)
C++ 代码
class Solution {
public:
    vector<vector<int>> findContinuousSequence(int target) {
        vector<vector<int>> res;
        vector<int> path;
        
        for (int i = 1, j = 1, sum = 0; i < target; i ++ ) {
            while (j < target && sum < target) sum += j, j ++ ;
            if (sum == target) {
                for (int k = i; k < j; k ++ ) path.push_back(k);
                res.push_back(path);
                path.clear();
            }
            sum -= i;
        }
        return res;
    }
};Java 代码
class Solution {
    public int[][] findContinuousSequence(int target) {
        List<int[]> res = new ArrayList<>();
        
        for (int i = 1, j = 1, sum = 0; i < target; i ++ ) {
            while (j < target && sum < target) {
                sum += j;
                j ++ ;
            }
            if (sum == target) {
                int[] path = new int[j - i];
                for (int k = i; k < j; k ++ ) {
                    path[k - i] = k;
                }
                res.add(path);
            }
            sum -= i;
        }
        return res.toArray(new int[res.size()][]);
    }
}
Python 代码
class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        res = []
        path = []
        
        i, j, s = 1, 1, 0
        while i < target:
            while j < target and s < target:
                s += j
                j += 1
            if s == target:
                path = list(range(i, j))
                res.append(path[:])
                path.clear()
            s -= i
            i += 1
        return res题解 2
(回溯)
将每个数作为起点开始找合法方案并记录路径和,如果 sum == target,则将路径加入答案中。
剪枝优化:
- 如果和 sum > target 说明不是一个合法方案,直接返回。
- 如果当前正在遍历的数和路径中的最后一个数不是相邻的,也不是一个合法方案,直接 break 结束当前搜索分支。
时间复杂度
回溯的时间复杂度一般是指数级别的,由于这道题目合法方案数比较少,可以过。
空间复杂度
O(n)
C++ 代码
class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    void dfs(int start, int sum, int target) {
        if (sum > target) return;
        if (start == target) return;
        if (sum == target) {
            res.push_back(path);
            return;
        }
        for (int i = start; i < target; i ++ ) {
            if (path.size() && path.back() + 1 != i) break;
            path.push_back(i);
            dfs(i + 1, sum + i, target);
            path.pop_back();
        }
    }
    vector<vector<int>> findContinuousSequence(int target) {
        dfs(1, 0, target);
        return res;
    }
};Java 代码
class Solution {
    List<int[]> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    void dfs(int start, int sum, int target) {
        if (sum > target || start == target) {
            return;
        }
        if (sum == target) {
            int[] pathArray = new int[path.size()];
            for (int i = 0; i < path.size(); i ++ ) {
                pathArray[i] = path.get(i);
            }
            res.add(pathArray);
            return;
        }
        for (int i = start; i < target; i ++ ) {
            if (!path.isEmpty() && path.get(path.size() - 1) + 1 != i) {
                break;
            }
            path.add(i);
            dfs(i + 1, sum + i, target);
            path.remove(path.size() - 1);
        }
    }
    int[][] findContinuousSequence(int target) {
        dfs(1, 0, target);
        int[][] result = new int[res.size()][];
        for (int i = 0; i < res.size(); i++) {
            result[i] = res.get(i);
        }
        return result;
    }
}Python 代码
class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        res = []
        path = []
        def dfs(start, total, target):
            if total > target or start == target:
                return
            if total == target:
                res.append(path[:])
                return
            for i in range(start, target):
                if path and path[-1] + 1 != i:
                    break
                path.append(i)
                dfs(i + 1, total + i, target)
                path.pop()
        dfs(1, 0, target)
        return res本文由读者提供,Github地址:https://github.com/tonngw
点击面试手册,获取本站面试手册PDF完整版