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

785 阅读4分钟

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

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第6篇文章 点击查看文章详情 🚀🚀

这次废话不多说,直接上题目!!!

977. 有序数组的平方 - 力扣(LeetCode)

难度:🔥🔥

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

示例 1:

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

直接上暴力解法

    let len = nums.length;
    for(let i = 0;i < len ;i++){
        nums[i] = nums[i]*nums[i];
    }
    nums.sort((a,b) => a - b)
    return nums

但暴力解法怎么可能满足我们呢

双指针

    let res = [];
    let len = nums.length;
    let left = 0;
    let right = len - 1;
    while(left <= right){
        let numsl = nums[left] * nums[left];
        let numsr = nums[right] * nums[right];
        if(numsl >= numsr){
            res.unshift(numsl);
            left ++ ;
        }
        else{
            res.unshift(numsr);
            right -- ;
        }
    }
    return res;

之所以能够应用双指针是因为数组的最大值只可能出现在最两侧,直接遍历一次就能出来结果了

难点

  • 数组的api

Array.unshift() 用的比较少

  • 双指针的应用场景也比较少,一时半会想不到。

209. 长度最小的子数组 - 力扣(LeetCode)

难度:🔥🔥🔥

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

 
示例 1:

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

滑动窗口

    const len = nums.length;
    let l = r = sum = 0;
    let res = len + 1; // 长度不可能超过该值
    while(r < len) {
        sum += nums[r];
        r++;
        // 窗口滑动
        while(sum >= target) {
            // r始终为开区间 [l, r)
            res = res < r - l ? res : r - l;
            sum-=nums[l];
            l++;
        }
    }
    return res > len ? 0 : res;

难点

  • 滑动窗口的过程

    1. 先用r去寻找目标窗口区间

    2. 移动l缩小窗口区间

      因为题目要求的是长度最小

      避免 [1,1,1,1,100] target = 101 类似这种情况

    3. 再启动r去寻找后续是否还有满足的情况

  • 最小长度的写法

    1. 先初始化res= len + 1

    2. 用三目运算符

      res = res < r - l ? res : r - l;

  • sum的值从始至终都 < target

    return res > len ? 0 : res;

59. 螺旋矩阵 II - 力扣(LeetCode)

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

 

示例 1:

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

难点:🔥🔥🔥🔥

模拟数组

    let startX = startY = 0;
    let loop = Math.floor(n/2);// 转的圈数
    let mid = Math.floor(n/2);
    let offset = 1;
    let count = 1;
    let res = new Array(n).fill(0).map(() => new Array(n).fill(0)); // 创建二维数组
    
    while(loop--){
        let i = startX;
        let j = startY;
        for(;j < n - offset;j++){
            res[i][j] = count;
            count++;
        }
        for(;i < n - offset;i++){
            res[i][j] = count;
            count++;
        }
        for(;j > startY;j--){
            res[i][j] = count;
            count++;
        }
        for(;i > startX;i--){
            res[i][j] = count;
            count++;
        }
        startX++;
        startY++;
        offset++;
    }

    if((n%2) != 0){
    res[mid][mid] = count++;
    }  // 如果n为奇数,最后一个数 => 图像的中间值

   return res;

难点

  • js中二维数组的创建

    let res = new Array(n).fill(0).map(() => new Array(n).fill(0));

  • 模拟区间的掌握

    要提前确定好一个遍历的区间,这里我采用的是左闭右开。

    n = 4 时,第一圈边遍历时,只会遍历个值,即[一条边的开始,边的末尾)

  • offset

    因为每转完一圈,单边可以遍历的值不仅与startX,startY有关,还有一个因素——offset

  • 圈数

    let loop = Math.floor(n/2);

    刚开始也很不理解为什么是这样求的

image.png 但看了b站上大佬的讨论后,豁然开朗~

  • 奇数的求法

我吐了,总是会写成n/2,再这么写要把我手剁了

收获

今天花了四个多小时在算法上面,还好时间还够,也还好这次效率也很高,不会再和以前一样眼高手低,囫囵吞枣般刷题了。

  1. 收获了双指针的应用场景
  2. 掌握了滑动窗口方法
  3. 对二维数组转圈圈也没原先那么恐惧了

⭐⭐⭐

加油,明天见!!