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

977、有序数组的平方


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

**示例 1:**

**输入:**nums = [-4,-1,0,3,10]
**输出:**[0,1,9,16,100]
**解释:**平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

**示例 2:**

**输入:**nums = [-7,-3,2,3,11]
**输出:**[4,9,9,49,121]

想法:这道题刚拿到手,Carl建议使用双指针,于是从双指针入手
这个 `sortedSquares` 方法接受一个整数数组 `nums` 作为输入,其中可能包含正数和负数。它对数组中的每个元素进行平方,将平方值按非递减顺序排序,并返回结果数组。

这是算法的详细步骤:

1. 初始化两个指针,`left` 指向数组的起始位置(`0`),`right` 指向数组的末尾(`nums.length - 1`)。
2. 创建一个新数组 `result`,用于存储平方后的值,长度与输入数组 `nums` 相同。
3. 初始化一个 `index` 变量,指向 `result` 数组的最后一个索引(`result.length - 1`)。
4. 使用 while 循环遍历数组 `nums`,直到 `left` 指针小于等于 `right` 指针。
5. 比较 `left` 和 `right` 指针处数字的平方。
6. 如果 `left` 指针处数字的平方大于 `right` 指针处数字的平方,将 `left` 指针处数字的平方插入到 `result` 数组的 `index` 位置,并将 `left` 指针向右移动一位。
7. 否则,将 `right` 指针处数字的平方插入到 `result` 数组的 `index` 位置,并将 `right` 指针向左移动一位。
8. 将 `index` 变量减一。
9. 循环结束后,`result` 数组将包含按非递减顺序排序的 `nums` 数组中元素的平方值。

这个算法利用了负数的平方是按降序排列的,而正数的平方是按升序排列的这一事实。因此,当合并两个已排序的半段(正数平方和负数平方)时,我们只需比较两端的值,以确定应将哪个值插入到结果数组中。

代码:

class Solution {

    public int[] sortedSquares(int[] nums) {

        int left = 0;

        int right = nums.length-1;

        int[] result = new int[nums.length];

        int index = result.length-1;

        while(left<=right){

            if(nums[left]*nums[left]>nums[right]*nums[right]){

                result[index--]=nums[left]*nums[left];

                left++;

            }

            else{

                result[index--]=nums[right]*nums[right];

                right--;

            }

        }

        return result;

    }

}

209、长度最小的子数组


给定一个含有 `n` 个正整数的数组和一个正整数 `target` **。**

找出该数组中满足其总和大于等于 `target` 的长度最小的 **连续**

**子数组**

 `[numsl, numsl+1, ..., numsr-1, numsr]` ,并返回其长度**。**如果不存在符合条件的子数组,返回 `0` 。

**示例 1:**

**输入:**target = 7, nums = [2,3,1,2,4,3]
**输出:**2
**解释:**子数组 `[4,3]` 是该条件下的长度最小的子数组。

**示例 2:**

**输入:**target = 4, nums = [1,4,4]
**输出:**1

**示例 3:**

**输入:**target = 11, nums = [1,1,1,1,1,1,1,1]
**输出:**0

本题关键在于理解滑动窗口,相当于用一个for循环做两个for循环要做的事情,right指向滑动窗口里的终止位置,所以要思考如何移动起始位置。
当我们起点和终点这个集合里面的元素>=target,说明这是符合条件的集合,收集当前的长度之后,起始位置就可以向后移动,再缩小现在的集合,来看下一个集合是否符合条件。

这里是算法的详细步骤:

1. 初始化两个指针 `left` 和 `right`,都指向数组的起始位置(`0`)。
2. 初始化一个变量 `result` 为整数的最大值 `Integer.MAX_VALUE`,用于存储找到的最短子数组的长度。
3. 初始化一个变量 `sum` 为 `0`,用于计算当前子数组的和。
4. 使用 `for` 循环遍历数组 `nums`,其中 `right` 指针从 `0` 开始,直到数组的末尾。
5. 在循环中,累加 `nums[right]` 到 `sum` 中。
6. 使用 `while` 循环,当 `sum` 大于或等于 `target` 时,执行以下操作:
    - 更新 `result` 为当前子数组的长度 `right - left + 1` 和 `result` 之间的较小值。
    - 从 `sum` 中减去 `nums[left]`。
    - 将 `left` 指针向右移动一位。
7. 重复步骤 5 和 6,直到 `right` 指针遍历完整个数组。
8. 返回 `result`,如果 `result` 仍然是 `Integer.MAX_VALUE`,则返回 `0`,表示数组中没有和大于或等于 `target` 的子数组。

这个算法使用了滑动窗口的技巧,通过移动 `left` 和 `right` 指针来动态地调整子数组的范围,并在满足条件时更新最短子数组的长度。这样可以在 `O(n)` 的时间复杂度内找到结果,其中 `n` 是数组 `nums` 的长度。

实现代码:

class Solution {

    public int minSubArrayLen(int target, int[] nums) {

        int left = 0;

        int right = 0;

        int result = Integer.MAX_VALUE;

        int sum = 0;

        for(right = 0;right < nums.length;right++){

            sum = sum + nums[right];

            while(sum >= target){

                result = Math.min(result,right-left+1);

                sum = sum - nums[left];

                left++;

            }

        }

        return result == Integer.MAX_VALUE ? 0 : result;

    }

}

59、螺旋矩阵Ⅱ


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

**示例 1:**

![](https://assets.leetcode.com/uploads/2020/11/13/spiraln.jpg)

**输入:**n = 3
**输出:**[[1,2,3],[8,9,4],[7,6,5]]

**示例 2:**

**输入:**n = 1
**输出:**[[1]]

算法的详细步骤:

1. 初始化四个变量 `l`、`r`、`t`、`b`,分别表示当前填充的矩阵边界的左、右、上、下位置,初始值都为 `0` 到 `n - 1`。
2. 创建一个大小为 `n x n` 的二维数组 `mat`,用于存储生成的螺旋矩阵。
3. 初始化两个变量 `num` 和 `tar`,分别表示当前填充的数字和总共需要填充的数字数量,初始值分别为 `1` 和 `n x n`。
4. 使用 `while` 循环,循环条件是 `num` 小于等于 `tar`,即还未填充完整个矩阵。
5. 在循环中,依次执行以下步骤:
    - 从左到右:使用 `for` 循环填充当前行 `t`,列从 `l` 到 `r`,填入数字 `num`,并递增 `num`。
    - 更新上边界 `t`,向下移动一行。
    - 从上到下:使用 `for` 循环填充当前列 `r`,行从 `t` 到 `b`,填入数字 `num`,并递增 `num`。
    - 更新右边界 `r`,向左收缩一列。
    - 从右到左:使用 `for` 循环填充当前行 `b`,列从 `r` 到 `l`,填入数字 `num`,并递增 `num`。
    - 更新下边界 `b`,向上收缩一行。
    - 从下到上:使用 `for` 循环填充当前列 `l`,行从 `b` 到 `t`,填入数字 `num`,并递增 `num`。
    - 更新左边界 `l`,向右移动一列。
6. 循环结束后,所有数字都已经填充完毕,返回生成的螺旋矩阵 `mat`。这个算法通过不断更新边界位置和填充数字,按照顺时针螺旋的方式逐步生成完整的矩阵。
代码如下所示:

class Solution {

    public int[][] generateMatrix(int n) {

        int l = 0, r = n - 1, t = 0, b = n - 1;

        int[][] mat = new int[n][n];

        int num = 1, tar = n * n;

        while(num <= tar){

            for(int i = l; i <= r; i++) mat[t][i] = num++; // left to right.

            t++;

            for(int i = t; i <= b; i++) mat[i][r] = num++; // top to bottom.

            r--;

            for(int i = r; i >= l; i--) mat[b][i] = num++; // right to left.

            b--;

            for(int i = b; i >= t; i--) mat[i][l] = num++; // bottom to top.

            l++;

        }

        return mat;

    }

}
  • 46
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值