Carl代码随想录算法训练营-Day 2- 209.长度最小的子数组、59.螺旋矩阵II

本文介绍了两道编程题目,一是如何使用滑动窗口优化暴力解法求解长度最小的子数组,二是控制二维数组下标生成螺旋矩阵。作者强调了算法思维和文档写作在编程学习中的重要性。

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

209、长度最小的子数组

力扣链接

暴力解法

思路

第一眼初窥这道题,我并没有想到暴力解法。这道题的暴力解法也就是用嵌套的for循环,外层for循环遍历作为子数组的左边界i,内层for循环遍历作为子数组的右边界j,还要维护一个sum变量用来求子数组的和,每次外循环的时候重新声明,每次内循环的时候sum++,然后判断sum>=target
不难想到其时间复杂度是 O(n2)。

实现

//略

滑动窗口

在暴力解法的基础上,就可以很自然地想到,当j在向右移动的过程中,首次满足了sum>=target条件的时候,[i,j]子数组肯定是此次外循环中长度最小的数组了,因为[i,j]<=[i,j+c],因此这时候就可以停下了。
同时我们发现,完全可以让i在满足sum>=target的条件下也跟着j向右移动。这样的话,一个二维的for循环就被拍扁成为一维的for循环了,通过一层for循环即可控制ij两个指针的变化。

实现

class Solution {
        public int minSubArrayLen(int target, int[] nums) {
            int min = Integer.MAX_VALUE;
            int i = 0, j = 0;
            for (int sum = 0; j < nums.length; j++) {
                sum += nums[j];
                while (sum >= target) {
                    min = Math.min(min, j - i + 1);
                    sum -= nums[i++];
                }
            }
            return min == Integer.MAX_VALUE ? 0 : min;
            //防止整个nums都不能满足target
        }
    }

59、螺旋矩阵II

思路

这道题不涉及到什么算法,单纯考察对二维数组下标的控制能力。
经过一段时间的观察不难发现,如果把整个螺旋过程看成转圈的话,每转一圈能填满4条边,2列2行,故而一个n阶方阵要转n/2圈才能填满。
需要注意的是,如果n为奇数的话,那么就有一行一列需要单独画,也就是最中间的那个格子,同时也是最后一个填的格子,它的下标是[n/2][n/2]
在这里插入图片描述

这时候就可以对变量进行定义了,我们妨设当前是第offset圈,那么offset的范围就是[0,n/2),这样保证循环了n/2次。
每一圈要拆分还要拆分为四条边,每条边分别用一个循环来遍历。如下所示是第offset圈时的情况。
第offset圈时的情况

因此很容易就能写出四个for循环的初始值和终止条件了,但还要注意的是循环不变量分别是什么:

  1. 行:offset 列:[offset,n-offset-1)
  2. 行:[offset,n-offset-1) 列:n-offset-1
  3. 行:n-offset-1 列:[offset,n-offset-1)(递减)
  4. 行:[offset,n-offset-1)(递减) 列:offset
    有没有一种对称的美呢?🤫

实现

有了以上分析,代码就是手到擒来了

public int[][] generateMatrix(int n) {
            int[][] ans = new int[n][n];
            int count = 1;
            for (int i = 0; i < n >> 1; i++) {
                int border = n - i - 1;
                for (int j = i; j < border; j++) {
                    ans[i][j] = count++;
                }
                for (int j = i; j < border; j++) {
                    ans[j][border] = count++;
                }
                for (int j = border; j > i; j--) {
                    ans[border][j] = count++;
                }
                for (int j = border; j > i; j--) {
                    ans[j][i] = count++;
                }
            }
            if ((n & 1) == 1) ans[n >> 1][n >> 1] = count;
            //填充中心格子
            return ans;
        }

总结

以上就是代码随想录算法训练营第二天的任务了。不得不说,以前还不信编码只是程序员很小的一部分工作,更多的是写文档,现在见识到了。如果说写代码花了一小时,那么写一篇博客就要花三小时。但是坚持写博客是有好处的,在写博客的过程中不仅分享了思路,更能帮助咱们缕清算法思维。
永远不要去觉得博客没人看就没必要写,因为只要你写了,那么你就没必要再去思考写这篇博客到底有没有必要了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值