和为s的连续正数序列----滑动窗口经典题目(简单难度)

简介: 和为s的连续正数序列----滑动窗口经典题目(简单难度)

目录

题目概述(简单难度)

思路与代码

思路展现(滑动窗口)

代码示例

代码解析:

总结

题目概述(简单难度)

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。


序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。


示例 1:

输入:target = 9
输出:[[2,3,4],[4,5]]

示例 2:


输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]

题目链接:

点我进入leetcode


思路与代码

思路展现(滑动窗口)

这道题目是数组中非常经典的滑动窗口的题目, 题解看个就行:

点我进入题解

但是有几个需要注意的点

1:首先注意我们的滑动区间是一个左闭右开的区间

2:后期不管是我们的区间是大还是小,我们的窗口的左边界和右边界永远只能向右移动


代码示例

class Solution {
    public int[][] findContinuousSequence(int target) {
        // 滑动窗口的左边界
        int i = 1;
        // 滑动窗口的右边界
        int j = 1;
        //滑动窗口内的值的总和
        int sum = 0;
        /*
        i如果大于target/2的话,就不存在连续正整数序列了
        */
        //定义一个list用于存储我们连续正整数数列,存储的类型为int[]
        List<int[]> list = new ArrayList<>();
        while(i <= target / 2) {
            if(sum < target) {
                // 右边界向右移动
                sum += j;
                //注意j++才能保证是一个左闭右开区间
                j++;
            }else if(sum > target) {
                // 左边界向右移动
                sum -= i;
                i++;
            }else {
                //因为是左闭右开区间,所以次数应该是j-i,而不是j-i+1,大家可以仔细体会
                //创建一个数组,把我们每次符合条件的数组进行存储
                int[] arr = new int[j-i];
                for(int k = i ; k < j ; k++) {
                    //注意要把符合条件的数字存入我们的arr数组,这里的设计比较巧妙,大家好好体会
                    arr[k-i] = k;
                }
                //存储完毕后放入到我们的list集合
                list.add(arr);
                //此时我们找到一组后,开始找下一组,是让i++,并且从总数sum中减掉我们的i
                sum -= i;
                i++;
            }
        }
        //循环完毕后我们list中所存储的就是我们所有符合条件的连续正整数序列,然后使用toArray方法将其转换为二维数组
        return list.toArray(new int[0][]);
    }
}

2.png

代码解析:

这段代码还是有很多设计的比较精妙的地方的,我们来解析一下代码:

1:

while(i <= target / 2)

滑动窗口的循环条件改成i <= target/2更好,因为要求是连续正整数,第一个数大于target的一半就不可能了

2:

int[] arr = new int[j-i]

因为是左闭右开区间,所以次数应该是j-i,而不是j-i+1,大家可以仔细体会

3:

 arr[k-i] = k;

注意要把符合条件的数字存入我们的arr数组,这里的设计比较巧妙,大家好好体会

4:

sum -= i;
i++;

这两步是必不可少的,原因是当我们找到了连续的正整数序列后,此时需要继续往下找,我们的方法是让我们的i往后走,从i+1开始,然后再继续判断,同时我们的总数sum需要减掉我们的i.

5:

return list.toArray(new int[0][]);

这一步就是把我们的list集合转变为数组进行返回,大家可以通过这篇博客来复习一下集合转数组.

点我进入掘金

可以看到我们这里我们为什么是0,不是res.size()或者其他的,原因就是数组空间等于0时,将会动态的创建和集合size相同空间大小的数组,性能是最好的。


总结

考察对于数组滑动窗口的掌握


相关文章
|
2月前
|
算法 测试技术 程序员
力扣经典150题第三十题:长度最小的子数组
力扣经典150题第三十题:长度最小的子数组
13 1
|
2月前
|
存储 算法 数据可视化
哈希表法快速求解最长连续序列 | 力扣128题详细解析
哈希表法快速求解最长连续序列 | 力扣128题详细解析
|
2月前
【LeetCode刷题】滑动窗口思想解决:最大连续1的个数 III、将x减到0的最小操作数
【LeetCode刷题】滑动窗口思想解决:最大连续1的个数 III、将x减到0的最小操作数
|
2月前
【LeetCode刷题】滑动窗口思想解决问题:长度最小的子数组、无重复字符的最长子串
【LeetCode刷题】滑动窗口思想解决问题:长度最小的子数组、无重复字符的最长子串
|
3月前
【错题集-编程题】删除相邻数字的最大分数(动态规划 - 线性 dp)
【错题集-编程题】删除相邻数字的最大分数(动态规划 - 线性 dp)
|
3月前
|
算法 测试技术 C++
【数论】【分类讨论】【C++算法】1611使整数变为 0 的最少操作次数
【数论】【分类讨论】【C++算法】1611使整数变为 0 的最少操作次数
【力扣每日一题:2-19】1004. 最大连续1的个数 III【中等】
【力扣每日一题:2-19】1004. 最大连续1的个数 III【中等】
Leecode 面试题57 - II. 和为s的连续正数序列
Leecode 面试题57 - II. 和为s的连续正数序列
41 0
LeetCode 1913. 两个数对之间的最大乘积差
两个数对 (a, b) 和 (c, d) 之间的 乘积差 定义为 (a * b) - (c * d) 。
63 0