代码随想录算法训练营第二天| 209. 长度最小的数组、977.有序数组的平方、59. 螺旋矩阵II

762 阅读4分钟

徘徊于螺旋中

209.长度最小的数组

题目链接 leetcode.cn/problems/mi…

题目要求:给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

代码:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int length = 100001;
        int sum = 0;
        int left = 0; int right = 0;
        for (; right < nums.length; right++) {
            sum += nums[right];
            while (sum >= target) {
                sum -= nums[left++];
                length = Math.min(right - left + 2, length);
            }
        }

        return length == 100001 ? 0 : length;
    }
}

解题之思考及结果

首先来看这道题,一眼得出暴力解法两个for循环可以解决,但这样必定会造成TLE,于是想着题目中要求的连续子数组是不是可以通过第一天学习的双指针来解决呢。于是想了一下。

定义left和right两个指针来动态地表示result数组下标。right在循环中起到把 nums[right] 加到sum的作用,left则作为在sum中减去nums[left]来判断是否还处在sum > target的作用。指针定义好了,那程序也就好写了,

我们可以用一个循环控制right不断++,以更新sum中的值,而当 sum >= target 的值的时候,代表着left和right之间可能有缩小距离的空间,这就是while循环的作用:用 sum -= nums[left++] 来尝试缩小left和right之间的距离,当距离小于当前的length时,即我们成功找到一个更小的连续子数组


977.有序数组的平方

题目链接:leetcode.cn/problems/sq…

题目要求:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

代码:

class Solution {
    public int[] sortedSquares(int[] nums) {
        int j = nums.length - 1;
        int i = 0;
        int k = j;
        int[] r = new int[nums.length];
        while (k >= 0) {
            if (nums[j] * nums[j] > nums[i] * nums[i]) {
                r[k--] = nums[j] * nums[j];
                j--;
            } else {
                r[k--] = nums[i] * nums[i];
                i++;
            }
        }
        return r;
    }
}

解题之思考及结果

初见依旧使用暴力解法,逐个平方再xx排序,而后看了Carl兄的思路实在惭愧,没有深入考虑整个数组有什么规律就直接断言了。

这道题倒有点意思,一个非递减排序的数组必定两边往中间平方数是递减的。那抓住这个规律就很简单了,只要判断两边的平方谁大,大的倒着放到新数组里面即可。


59. 螺旋矩阵II

题目链接:leetcode.cn/problems/sp…

题目要求:给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

image.png

代码:

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] result = new int[n][n];
        int i = 0, j = 0; // 行,列
        int loop = 0; // 控制循环
        int count = 1; // 每次填入数字
        int start = 0; // 每次开始位置
        while (loop++ < n / 2) {
            for (j = start; j < n - loop; j++){
                result[start][j] = count++;
            }
            for (i = start; i < n - loop; i++){
                result[i][j] = count++;
            }
            for (; j >= loop; j--){
                result[i][j] = count++;
            }
            for (; i >= loop; i--){
                result[i][j] = count++;
            }
            start++;
        }
        if (n % 2 == 1){
            result[start][start] = count;
        }
        
        return result;
    }
}

解题之思考及结果

今天大部分时间都是耗在这题里面,我感觉自己的算法或者说数学功底还是较差的,看官方示例图,虽然我有在找规律,但是找了半天也还是一无所获。实在想不出来了还是看了下代码随想录的视频讲解 一入循环深似海 | LeetCode:59.螺旋矩阵II

不得不说,学算法的时候有人教是真的舒服,思路不对不管想多久都是很难想出答案的,而看了视频,跟着大佬的思路走一遍之后,思维打开了,代码嘎嘎敲。

螺旋数组看起来其实很简单,而实际上还是要找好各边的边界,那这里采用的是左闭右开的区间来作判断,每条边忽略最后一位数,留给下一条边来处理。这样就不用因为边界问题而修修补补了。

循环次数和每轮循环开始位置也是一大难点,也是我一直不能确定的一个东西。其实每次循环可以看作更深入一圈,这里深入一圈代表的意思也是每次开始位置-1 和循环次数-1 的意思