代码随想录算法训练营第2天 | 209.长度最小的子数组、59螺旋矩阵Ⅱ

209.长度最小的子数组

题目链接:209.长度最小的子数组

1.解题思路

首先理解是数组中找连续的元素的和是target

暴力解法:两个循环

两个for循环,然后不断的寻找符合条件的子序列,时间复杂度很明显是O(n^2),力扣会超时。

是以外循环为起点,内循环为终点的加

滑动窗口:双指针

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

right指向终止位置,left指向起始位置,如果[left,right]中的和>=target,left右移找最小长度。

是以循环为终点,依次遍历。

时间复杂度:O(n)

2.遇到的问题

1.暴力解法时,result初始值设置错了,会在代码中给出

3.实现代码

暴力解法:

    public int minSubArrayLen(int target, int[] nums) {
        int result = nums.length+1; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        for (int i = 0; i < nums.length; i++) { // 设置子序列起点为i
            sum = 0;//每次进来sum置为0
            for (int j = i; j < nums.length; j++) { // 设置子序列终止位置为j
                sum += nums[j];
                if (sum >= target) { // 一旦发现子序列和超过了target,更新result
                    subLength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break,进入下一个外循环
                    break; 
                }
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        // 这个地方错了,如果刚好要所有加起来等于最终结果,那就有问题
        //return result == nums.length ? 0 : result;
        
        
        return result == nums.length+1 ? 0 : result;//选个比最大范围大的,不包含在那个范围

    }

滑动窗口:

public int minSubArrayLen(int target, int[] nums){
        int result = nums.length+1;
        int sum = 0; // 滑动窗口数值之和
        int i = 0; // 滑动窗口起始位置
        int subLength = 0; // 滑动窗口的长度
        for (int j = 0; j < nums.length; j++) {
            sum += nums[j];//left右移之后的sum加现在的right
            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
            while (sum >= target) {
                subLength = (j - i + 1); // 取子序列的长度
                result = result < subLength ? result : subLength;
                sum -= nums[i]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
                i++;//left右移
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == nums.length+1 ? 0 : result;

    }

4.题目总结

滑动窗口:确定何时扩大窗口,确定何时缩小窗口,在窗口滑动的哪个阶段更新结果,怎么移动窗口(不断变更i(子序列的起始位置))。

59.螺旋矩阵Ⅱ

题目链接:螺旋矩阵Ⅱ

1.解题思路

要写出正确的二分法一定要坚持循环不变量原则,即每一次循环的处理规则要一致

在这里我们是左闭右开原则,每一条边的边界条件都一样,每一次循环的条件也一样。

2.遇到的问题

1.边界条件错误

3.实现代码

public int[][] generateMatrix(int n) {
        int[][] nums = new int[n][n];
        int startX = 0, startY = 0;  // 每一圈的起始点
        int offset = 1;
        int count = 1;  // 矩阵中需要填写的数字
        int loop = 1; // 记录当前的圈数
        int i, j; // j 代表列, i 代表行;

        while (loop <= n / 2) {

            // 顶部
            // 左闭右开,所以判断循环结束时, j 不能等于 n - offset
            for (j = startY; j < n - offset; j++) {
                nums[startX][j] = count++;
            }

            // 右列
            // 左闭右开,所以判断循环结束时, i 不能等于 n - offset
            for (i = startX; i < n - offset; i++) {
                nums[i][j] = count++;
            }

            // 底部
            // 左闭右开,所以判断循环结束时, j != startY
            for (; j > startY; j--) {
                nums[i][j] = count++;
            }

            // 左列
            // 左闭右开,所以判断循环结束时, i != startX
            for (; i > startX; i--) {
                nums[i][j] = count++;
            }
            startX++;
            startY++;
            offset++;
            loop++;
        }
        if (n % 2 == 1) { // n 为奇数时,单独处理矩阵中心的值
            nums[startX][startY] = count;
        }
        return nums;
    }

4.题目总结

可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此offer是路人。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值