Day02~977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

285 阅读5分钟

摘要

这篇文章聚焦于三个算法题:LC-977. 有序数组的平方、LC-209. 长度最小的子数组和LC-59. 螺旋矩阵 II,并最后由ChatGPT对数组专题进行了全面总结。

1、LC-977.有序数组的平方

1.1 思路

双指针,分别指向数组的头尾,比较平方大小,从大到小依次放入新数组中,直到处理完所以元素

  • 双指针往中间走
  • 比较大小新数组留

1.2 代码

    // 双指针,分别指向数组的头尾,比较平方大小,从大到小依次放入新数组中,直到处理完所以元素
    public static int[] sortedSquares(int[] nums) {
        int left = 0, right = nums.length-1;
        int[] res = new int[nums.length];
​
        int idx = nums.length -1;
        while(left <= right) {
            int num1 = nums[left] * nums[left];
            int num2 = nums[right] * nums[right];
            if(num1 > num2) {
                res[idx] = num1;
                left++;
            } else {
                res[idx] = num2;
                right--;
            }
            idx--;
        }
        return res;
    }

2、LC-209.长度最小的子数组

2.1 思路

双指针/滑动窗口 left, right分表代码连续子数组的头尾下标;sum表示该连续子数组的总和;res表示连续子数组的最小长度 right一直右移,直至sum大于等于target,计算出res;在满足条件的情况下,left也一直右移,不断更新res

  • 左右指针滑窗舞,Sum为子数组求和妙
  • 右指针向右移,Sum大于等于目标值,这是重要的起始
  • 得到满足条件的长度,左指针缩小窗口,继续寻找最小的长度

2.2 代码

// 双指针/滑动窗口
// left, right分表代码连续子数组的头尾下标;sum表示该连续子数组的总和;res表示连续子数组的最小长度
// right一直右移,直至sum大于等于target,计算出res;在满足条件的情况下,left也一直右移,不断更新res
    public static int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int sum = 0;
        int res = Integer.MAX_VALUE;
​
        for (int right = 0; right < nums.length; right++) {
            sum += nums[right];
            while (sum >= target) {
                res = Math.min(res, right - left + 1);
                sum -= nums[left];
                left++;
            }
        }
        return res != Integer.MAX_VALUE ? res : 0;
    }

3、LC-59.螺旋矩阵II

3.1 思路

1、如何确定循环次数?

loop = n / 2;如果遇到 n 是奇数的情况,单独给中间的元素赋值

2、如果确定起始位置的结束位置

起始位置:startx = 0;starty = 0;每转一圈 startx ++,starty ++ 结束位置:endx = n-1, endy = n-1;每转一圈 endx --,endy --

3、如何表示二维数组中元素的值

定义计数变量 count,表示二维数组中元素的值

4、保持循环不变量(左闭右开)

  • i=startx; j=[starty, endy)
  • i=[startx, endx); j=endy
  • i=endx; j=[endy, starty)
  • i=[endx, startx); j=starty

3.2 代码

public static int[][] generateMatrix(int n) {
    int[][] res = new int[n][n];
​
    // 循环次数
    int loop = n / 2;
    // 起始位置
    int startx = 0, starty = 0;
    // 结束位置
    int endx = n - 1, endy = n - 1;
    // 二维数组元素值
    int count = 1;
​
    while (loop > 0) {
        // i=startx;j=[starty, endy)
        for (int j = starty; j < endy; j++) {
            res[startx][j] = count;
            count++;
        }
​
        // i=[startx, endx);j=endy
        for (int i = startx; i < endx; i++) {
            res[i][endy] = count;
            count++;
        }
​
        // i=endx;j=[endy, starty)
        for (int j = endy; j > starty; j--) {
            res[endx][j] = count;
            count++;
        }
​
        // i=[endx, startx);j=starty
        for (int i = endx; i > startx; i--) {
            res[i][starty] = count;
            count++;
        }
​
        startx++;
        starty++;
        endx--;
        endy--;
        loop--;
    }
​
    // 处理n=奇数的情况
    if (n % 2 == 1) {
        res[startx][starty] = count;
    }
    return res;
}

4、总结

以下是对提到的五个数组算法题的总结:

  1. LC-704. 二分查找

    • 主要思路:使用二分查找的方法在有序数组中查找目标元素。
    • 具体步骤:使用两个指针,leftright,初始化分别指向数组的起始和结束位置。然后,在每一轮循环中,计算中间位置 mid,并比较 nums[mid] 与目标值 target。如果相等,返回 mid;如果小于 target,则将 left 向右移动到 mid + 1;如果大于 target,则将 right 向左移动到 mid - 1
    • 时间复杂度:O(log n),因为每一轮都将搜索范围减半。
  2. LC-27. 移除元素

    • 主要思路:通过双指针遍历数组,将不等于目标值的元素移到前面。
    • 具体步骤:使用两个指针,newIdxoldIdx,初始化分别为0。遍历数组,当发现元素等于目标值时,跳过;否则,将元素复制到 newIdx 位置,然后 newIdx 自增。最后,返回 newIdx 即为新数组的长度。
    • 时间复杂度:O(n),其中 n 为数组长度。
  3. LC-977. 有序数组的平方

    • 主要思路:利用有序数组的特性,通过双指针从两端向中间遍历,比较平方值的大小。
    • 具体步骤:使用两个指针,leftright,初始化分别指向数组的头和尾。比较 nums[left]nums[right] 的平方值,将较大的平方值放入结果数组的末尾,然后移动对应的指针。重复此过程直到两个指针相遇。
    • 时间复杂度:O(n),其中 n 为数组长度。
  4. LC-209. 长度最小的子数组

    • 主要思路:使用双指针/滑动窗口技巧,维护一个子数组的窗口,不断调整窗口大小以满足条件。
    • 具体步骤:使用两个指针,leftright,分别初始化为0。left 一直右移,直到子数组的和大于等于目标值 target,此时记录子数组的长度。然后,继续移动 left,不断尝试缩小子数组的长度,更新最小长度。重复这个过程直到 right 到达数组末尾。
    • 时间复杂度:O(n),其中 n 为数组长度。
  5. LC-59. 螺旋矩阵 II

    • 主要思路:按照顺时针的方向填充矩阵。
    • 具体步骤:使用四个变量 top, bottom, left, right 分别表示当前填充区域的上、下、左、右边界。然后,按照顺时针的顺序,从左到右、从上到下、从右到左、从下到上,填充矩阵的每一行或每一列。同时,更新边界变量,缩小填充区域。重复这个过程直到填充完成。
    • 时间复杂度:O(n^2),其中 n 为矩阵的边长。

这些算法题涵盖了数组相关的不同应用场景,包括搜索、修改、转换和填充等操作,对于理解数组算法和双指针/滑动窗口技巧都非常有帮助。

参考资料

代码随想录-有序数组的平方

代码随想录-长度最小的子数组

代码随想录-螺旋矩阵II