代码随想录第 2 天 - 977 有序数组的平方(双指针) & 209 长度最小的子数组(滑动窗口) & 59 螺旋矩阵II(模拟)

数组

977 有序数组的平方

原题链接

解题思路:
首先审题,题中描述是一个有序数组,数组中可能存在负数和正数,返回值是按照数的平方按非递减排序的数组。我们无法直接找到平方最小值在哪里,但是我们可以确定平方最大值一定是在数组的两端。于是就可以考虑用两个指针,一个指向数组最左端,一个指向最右端。每次对二者进行比较,然后进行赋值和下标更新。

题解(双指针):
时间复杂度:O(n)
空间复杂度:O(n)

class Solution {
    public int[] sortedSquares(int[] nums) {
        int n = nums.length;
        int[] res = new int[n]; // 新数组
        int left = 0;   // 左指针
        int right = n - 1;  // 右指针
        int index = n - 1;  // 新数组下标

        while (left <= right) {
            if (Math.abs(nums[left]) > Math.abs(nums[right])) {
                res[index] = nums[left] * nums[left];
                left++;
            } else {
                res[index] = nums[right] * nums[right];
                right--;
            }
            index--;
        }
        return res;
    }
}

209 长度最小的子数组

原题链接

题解1:

暴力解法: 直接遍历每个数,统计从每个数作为头节点开始向后累加,当长度大于等于 target 时记录子数组长度。

时间复杂度:O(n^2)
空间复杂度:O(1)

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int minLen = Integer.MAX_VALUE;

        for (int i = 0; i < nums.length; i++) {
            int sum = nums[i];
            int len = 1;
            if (sum >= target) return 1;
            for (int j = i + 1; j < nums.length; j++) {
                sum += nums[j];
                len++;
                if (sum >= target) {
                    minLen = Math.min(minLen, len);
                    break;
                }
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen;
    }
}

题解2:

滑动窗口: 当碰到子数组题时,可以考虑用滑动窗口。所谓滑动窗口,就是不断的调节子数组的起始位置和终止位置,从而得出我们要想的结果。
常用模版:for 循环 遍历数组 终止位置,内嵌一个while循环,循环条件为 想要的结果。当已经达到了想要的结果时,再不断 收缩起始位置

时间复杂度:O(n)
空间复杂度:O(1)

这里时间复杂度为 O(n) 的原因是,我们不能仅通过循环嵌套循环就断定为 O(n^2)。应该看数组中每个数实际被操作的次数。在此题中,数组中每个元素都被操作过两次,一次作为终止位置累加,一次作为起始位置累减。因此时间复杂度应是 O(2n) => O(n)。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int minLen = Integer.MAX_VALUE; // 求最小值,所以初始化最大值
        int start = 0;  // 标记子数组的头下标
        int sum = 0;    // 统计子数组的和
        int len = 0;    // 记录子数组长度

        // for循环遍历子数组的尾下标
        for (int end = 0; end < nums.length; end++) {
            sum += nums[end];   // 累加和

            // 当长度大于等于target时,先收集结果,然后收缩头节点
            while (sum >= target) {
                len = end - start + 1;
                minLen = Math.min(minLen, len);
                sum -= nums[start];
                start++;
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen;
    }
}

59 螺旋矩阵II

原题链接

解题思路:
比较经典的模拟题,先确定好四个边界,然后每次 for 循环后记得要收缩边界。

题解:
时间复杂度:O(n^2)
空间复杂度:O(n^2)

因为要填充 n*n 的数组,所以时间复杂度为 O(n^2);
除了返回的矩阵以外,空间复杂度为 O(1)。

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];
        int left = 0;   // 标记当前左边界
        int right = n - 1;  // 标记当前右边界
        int top = 0;    // 标记当前上边界
        int bottom = n - 1; // 标记当前下边界
        int num = 1;    // 计数

        while (num <= n * n) {
            for (int i = left; i <= right; i++) {
                res[top][i] = num;
                num++;
            }
            top++;

            for (int j = top; j <= bottom; j++) {
                res[j][right] = num;
                num++;
            }
            right--;

            for (int i = right; i >= left; i--) {
                res[bottom][i] = num;
                num++;
            }
            bottom--;

            for (int j = bottom; j >= top; j--) {
                res[j][left] = num;
                num++;
            }
            left++;
        }
        return res;
    }
}

今日心得

今天的题做的比较轻松,可能一刷的印象比较深。滑动窗口还需要再多做几道巩固一下🌹。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值