Day2 有序数组的平方+长度最小的子数组+螺旋矩阵II

文章介绍了三个算法问题的解决方案:有序数组的平方通过比较数组两端的平方值确定最大值;长度最小的子数组使用滑动窗口优化求解;螺旋矩阵II通过循环不变量模拟填充过程。每个问题都关注了时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

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

977. 有序数组的平方

题目链接: 977.有序数组的平方

思路:

数组其实是有序的, 只不过负数平方之后可能成为最大数了。所以数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
需要注意的是while里面的循环条件,每次i或者j都是变化1,,k要从len-1减到0,填满res数组,所以i=j那次才是最后一次。

代码部分:

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

时间复杂度:
O(n)
空间复杂度:
O(n) //创建了一个长度为 n 的数组来存储结果

209. 长度最小的子数组

题目链接: 209.长度最小的子数组

思路:

第一种想法,2层循环:第一层for循环控制区间的起始位置,第二层while循环控制区间的终止位置。
第二种:滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
分析:如果第一层循环是循环的窗口的起点位置,终止位置需要一个一个往后移,去搜集所有 >= target这些集合里面的所有的长度,再取一个最小的。这和两层循环的想法一样。所以第一层得是终点位置,然后动态的移动起点位置,从而减少时间复杂度。
终点位置随着for循环一个一个向后移动。如果我们的终点位置指向这里,这个集合里面的元素之和如果>= target的话,说明这是符合条件的一个集合,我们收集它的长度之后,起点位置就可以向后移动了。
从而缩小当前这个集合,看下一个集合是否符合我们的条件。

就是当我们发现集合里面所有的元素和 >= target,我们再去移动起始位置,这样就实现了动态调整起始位置,来去收集不同长度区间里面的和。

代码部分:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int res = Integer.MAX_VALUE;
        int subLen = 0;
        int sum = 0, start = 0;
        for(int end = 0; end < nums.length; end++){
            sum += nums[end];
            while(sum >= target){
                subLen = end - start + 1;
                res = res < subLen? res:subLen;
                sum -= nums[start];
                start++;
            }
        }
        return res == Integer.MAX_VALUE? 0:res;
    }
}

时间复杂度:
O(n)
看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)
空间复杂度:
O(1)

59. 螺旋矩阵II

题目链接:59.螺旋矩阵II

思路:

坚持循环不变量,左闭右开区间
模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

代码部分:

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];
        int loop = 0;
        int i, j; // i: col, j: row
        int start = 0;  // 每次循环的起点(start, start)
        int count = 1;
        while(loop < (n/2)){
            loop++; //判断边界后,loop从1开始
            // left to right - top
            for(i = start; i < n - loop; i++){
                res[start][i] = count++;
            }
            // top to bot - right
            for(j = start; j < n - loop; j++){
                res[j][i] = count++;
            }
            // right to left - bot
            for(; i >= loop; i--){
                res[j][i] = count++;
            }
            // bot to top - left
            for(; j >= loop; j--){
                res[j][i] = count++;
            }
            start++;
        }
        // 判断奇数时,需要给最中间赋值
        if(n%2 == 1){
            res[start][start] = count++;
        }
        return res;
    }
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值