【剑指 Offer 57 - II】和为s的连续正数序列 (滑动窗口)

题目

题目连接
输入一个正整数 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

没啥技巧纯暴力但超时

class Solution {
    public int[][] findContinuousSequence(int target) {
        List<List<Integer>> ans = new ArrayList<>();
        for (int i = 1; i < target; i++) {
            List<Integer> temp = new ArrayList<>();
            temp.add(i);
            int sum = i;
            for (int j = i + 1; j < target; j++) {
                temp.add(j);
                sum += j;
                if (sum == target) {
                    ans.add(temp);
                    break;
                }
            }
        }
        int[][] result = new int[ans.size()][];
        for (int i = 0; i < result.length; i++) {
            result[i] = new int[ans.get(i).size()];
            for (int j = 0; j < ans.get(i).size(); j++) {
                result[i][j] = ans.get(i).get(j);
            }
        }
        return result;
    }
}

解题思路2

滑动窗口问题

  • 当窗口中的每个元素的和小于 target 的时候,窗口的和需要增加,所以要扩大窗口,窗口的右边界向右移动
  • 当窗口中的每个元素的和大于 target 的时候,窗口的和需要减少,所以要缩小窗口,窗口的左边界向右移动
  • 当窗口中的每个元素的和等于target 的时候,记录从i到j的每一个元素装进结果集中,并且左右边界都有要右移

需要注意的是:左边界右移会缩小窗口和大小,所以记得减去左边界右移之前的值
代码详细流程:
在这里插入图片描述
在这里插入图片描述

class Solution {
    public int[][] findContinuousSequence(int target) {
        if (target <= 2) {
            return new int[0][0];
        }
        //结果集
        List<List<Integer>> ans = new ArrayList<>();
        int left = 1;
        int right = 2;
        int sum = left + right;
        while (left < right && right < target) {
            //如果sum==target说明找到一组正数序列,加入结果集后,准备下次寻找
            if (sum == target) {
                List<Integer> list = new ArrayList<>();
                for (int n = left; n <= right; n++) {
                    list.add(n);
                }
                ans.add(list);
                sum -= left;
                left++;
                right++;
                sum += right;
            //sum>target right再往后移也大于target所以将left++
            } else if (sum > target) {
                sum -= left;
                left++;
            } 
            //sum<target  right应该后移
            else {
                right++;
                sum += right;
            }

        }
        //处理结果 将list转化为数组
        int[][] result = new int[ans.size()][];
        for(int i = 0;i < result.length;i++){
            result[i] = new int[ans.get(i).size()];
            for(int j = 0;j < ans.get(i).size();j++){
                result[i][j] = ans.get(i).get(j);
            }
        }
        return result;

    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_35416214/article/details/107640306
今日推荐