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

本文探讨了如何找出所有连续正整数序列,这些序列的和等于给定的目标值。通过两种方法解决该问题:一种是暴力枚举,另一种是使用滑动窗口技术进行优化。文章提供了详细的代码实现,包括初始化结果集、移动窗口边界以及最终转换结果为数组的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

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

    }
}

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WormholeStack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值