Day02 | leetcode977. 有序数组的平方、leetcode209. 长度最小的子数组、leetcode59. 螺旋矩阵II、数组专题总结

leetcode977. 有序数组的平方

注意点:

  1. 题意是给一个有序数组,因此元素都是从小到大排列的,所以可以用相向双指针法来实现;
  2. 因为返回的是一个数组,所以要想到构建一个新数组用来存放排序好的元素;
  3. while() 循环的判断条件里要注意有个=号;
class Solution {
	// 相向双指针法
    public int[] sortedSquares(int[] nums) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;
        // 构建一个相等长度的新数组用来存放排序好的元素;从大排到小,因此指针指向最后一个元素
        int[] res = new int[len];
        int index = len - 1;
        // 注意有个=号不能漏,因为最后要处理两个元素
        while (right >= left) {
            if (nums[right] * nums[right] >= nums[left] * nums[left]) {
                res[index] = nums[right] * nums[right];
                index--;
                right--;
            } else {
                res[index] = nums[left] * nums[left];
                index--;
                left++;
            }
        }
        return res;
    }
}

拓展题目:

leetcode209. 长度最小的子数组

这题也是二刷的时候想对了思路,但是实现起来不太顺利。主要在于没弄清楚滑动窗口的起始位置和终止位置的更新方式,还得多写代码才行。

注意点:

  1. 滑动窗口:不断调节子序列的起始位置和终止位置,从而得出我们要想的结果;
  2. 在这题中实现滑动窗口法,主要确定这三点:
    窗口内是什么——满足其和 ≥ target 的长度最小的连续子数组;
    如何移动窗口的起始位置——如果当前窗口的总值大于 target,窗口就要向前移动了(也就是该缩小了,left–);
    如何移动窗口的结束位置——窗口的结束位置就是遍历数组的指针,也就是for循环里的索引(right < len)。
  3. 解题的关键在于窗口的起始位置如何移动;
  4. 滑动窗口法的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
class Solution {
	// 滑动窗口法
    public int minSubArrayLen(int target, int[] nums) {
        int len = nums.length;
        int left = 0; // 滑动窗口起始位置
        int sum = 0; // 滑动窗口数值之和
        int res = Integer.MAX_VALUE; // 先将结果值定义为整数型最大值
        for (int right = 0; right < len; right++) {
            sum += nums[right];
            // 注意这里使用while,每次更新 left(起始位置),并不断比较子序列是否符合条件
            while (sum >= target) {
                res = Math.min(res, right - left + 1);
                sum -= nums[left];
                left++; // 这里体现出滑动窗口的精髓之处,不断变更left(子序列的起始位置)
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return res == Integer.MAX_VALUE ? 0 : res;
    }
}

拓展题目:
904.水果成篮(opens new window)
76.最小覆盖子串

leetcode59. 螺旋矩阵II

此题代码主要依据力扣高赞题解,感觉比随想录的答案更好写。
注意点:

  1. 模拟法;更新
  2. 循环不变量原则;上下左右4个边界
  3. 使用 num <= tar 而不是 l < r || t < b 作为循环条件,是为了解决当 n 为奇数时,矩阵中心数字无法在循环过程中被填充的问题。
class Solution {
    public int[][] generateMatrix(int n) {
        // 定义当前左右上下边界 l,r,t,b
        int l = 0;
        int r = n - 1;
        int t = 0;
        int b = n - 1;
        // 定义输出矩阵mat,保存从 1 遍历到 n*n 的每个元素
        int[][] mat = new int[n][n];
        // 定义初始值 num = 1,循环终止值 tar = n * n
        int num = 1;
        int tar = n * n;
        // 当 num <= tar 时,始终按照 从左到右、从上到下、从右到左、从下到上 填入顺序循环
        while (num <= tar) {
            // left to right
            for (int i = l; i <= r; i++) {
                mat[t][i] = num++;
            }
            t++; // 更新上边界,内缩1个单位

            // top to bottom
            for (int i = t; i <= b; i++) {
                mat[i][r] = num++;
            }
            r--; // 更新右边界,内缩1个单位

            // right to left
            for (int i = r; i >= l; i--) {
                mat[b][i] = num++;
            }
            b--; // 更新下边界,内缩1个单位

            // bottom to top
            for (int i = b; i >= t; i--) {
                mat[i][l] = num++;
            }
            l++; // 更新左边界,内缩1个单位
        }
        return mat;
    }
}

拓展题目:
54.螺旋矩阵
剑指Offer 29.顺时针打印矩阵

数组专题总结

这个专题目前做了5题,涉及到了几种常见思路和方法:

  1. 二分法;(循环不变量原则:只有在循环中坚持对区间的定义,才能清楚的把握循环中的各种细节)
  2. 双指针法;(快慢指针法:通过一个快指针和慢指针在一个for循环下完成两个for循环的工作;相向双指针)
  3. 滑动窗口法;(重点是理解滑动窗口如何移动窗口起始位置,并达到动态更新窗口大小的条件)
  4. 模拟法;(真正解决题目的代码都是简洁的,或者有原则性的)

为了更好地写代码和保留自己的做题轨迹,我再本地IDE上专门建立了一个代码随想录的代码文件夹,里边会存放着未来2个月的刷题代码和注释,如下图所示。这样好处很多,也推荐给大家。之后二刷或者有时间就会把涉及到的那些拓展题也一并做了,加油!

Alt

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值