【代码随想录 | day02】(JavaScript)977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

977.有序数组的平方

我的解题思路

我的解题思路目前还是局限在使用库函数:

  1. 先使用map方法,对数组的每一个操作进行平方处理
  2. 使用sort排序。其实就可以扪心自问一下,sort底层原理是真的懂吗?

补充知识点:

双指针解法

时间复杂度为O(n),那么会有一次for循环。要搞清楚到底循环什么!

由于遍历数组,还是从两边遍历,所以这次的指针和之前的快慢指针还是有区别的。for循环中定义两个变量i, j(i = 0, j = nums.length - 1),用来当做双指针。

思路:

  1. 由于数组的特性是按 非递减顺序 排序的,所以数组元素平方过后,两边肯定是比中间大的。
  2. 先比较最左边和最右边的元素平方后的大小,确定最大值后,倒序放到新数组(长度和原数组一样)中
  3. 如果(nums[i])^2 < (nums[j])^2,那么newArr[k--]中放的就是(nums[j])^2,然后j--便于下一次的比较
  4. 若步骤3不成立,那么(nums[i])^2就有可能大于或许等于(nums[j])^2。那么newArr[k--]中放的就是(nums[i])^2,然后i++ 便于下一次的比较
/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    // let i = 0, j = nums.length - 1;
    let newArr = [];
    let k = nums.length - 1
    // 核心思路:双指针
    for(let i = 0, j = nums.length - 1;i <= j;) {
        if(nums[i] * nums[i] < nums[j] * nums[j]) {
            newArr[k--] = nums[j] * nums[j];
            j--;
        } else {
            newArr[k--] = nums[i] * nums[i];
            i++;
        }

    }
    return newArr
};

以上是我的代码。可以看看其他版本的js写法


209.长度最小的子数组

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

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

题目链接

滑动窗口解法
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

滑动窗口用到了for循环,for(j...),其中i, j是两个指针。那么i和j谁用作起始位置和终止位置是十分重要的。

一个for循环里面的 j ,指向的一定是终止位置。

(重点)如何移动起始位置?

如果说起始位置 i 在下标0那里,先for循环一个个移动终止位置 j (j=0;j<数组长度;j++)。通过 j 不断移动,求出起始和终止的这个区间里面元素相加的和,当和大于等于target时,就收集这个区间的长度。

每一次区间长度得到后,要拿当前的长度值和之前得到的长度值做一个比较,取出最小值。这样就能不断的更新区间的最小值。

⭐️当和大于等于target时,用 if 比较好还是 while 比较好?

答:用while。因为我们要的是起始位置持续向后移动,以此来更新滑动窗口大小。

什么时候用if,什么时候用while?

  • 当对一个条件进行一次判断时,可以使用if语句。
  • 当对一个条件进行多次判断时,可以使用while语句。

⭐️之前收集到的区间长度存在哪里了?不存起来怎么与现在的做一个比较?

答:在一开始先定义一个变量,存放一个特别大的数字,比如minL=Number.MAX_VALUE 然后再与当前区间的长度做比较。

⭐️求出起始和终止的这个区间里面元素相加的和,怎么个求法?

答:其实在进行for循环的时候,已经开始一步步累加了。

知识点补充:

以下是我的代码,参考文章中可以看到其他语言的相关解法。

var minSubArrayLen = function(target, nums) {
    let sum = 0;
    let start = 0;
    let result = Number.MAX_VALUE;  // 用于收集区间的长度
    for(let end = 0; end < nums.length; end++) {
        sum += nums[end];
        while(sum >= target) {
            let subL = end - start + 1;  // 当前区间的长度
            result = Math.min(result, subL);
            sum -= nums[start++];
        }
    }
    return result == Number.MAX_VALUE ? 0 : result;
    // return result
};

参考文章:


59.螺旋矩阵II

螺旋矩阵经常犯的一些毛病:

处理每一条边的时候,其实对节点的的处理规则都是不一样的。

思路
  1. 需要定义好的变量:

    • startx——控制x轴的坐标
    • starty——控制y轴的坐标
    • loop——控制圈数
    • mid——当n为奇数时,设置矩阵中间的位置。例如n=5,中间位置就是(2, 2)
    • count——用来给矩阵中的每一个空赋值
    • offset——控制每一条边遍历的长度,每次循环右边界收缩一位
    • 二维数组——let res = new Array(n).fill(0).map(() => new Array(n).fill(0));
  2. 输入n,那么会转几圈? 转n/2圈

  3. n是奇数怎么办?n为5时,矩阵中心的数就是25,除了中心的这个数,外面是2圈。

  4. 模拟顺时针画矩阵的过程:

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

    由外向内一圈一圈这么画下去。

每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来

/**
 * @param {number} n
 * @return {number[][]}
 */
var generateMatrix = function(n) {
    let startX = 0, startY = 0;
    let loop = Math.floor(n/2);
    let mid = Math.floor(n/2);
    let count = 1;
    let offset = 1;
    let res = new Array(n).fill(0).map(() => new Array(n).fill(0));
    
    while(loop--) {
        let i = startX; // 横坐标
        let j = startY; // 纵坐标

        // 左闭右开
        for(; j < startY + n - offset; j++) {
            res[i][j] = count++;
        }
        for(;i < startX + n - offset; i++) {
            res[i][j] = count++;
        }
        for(;j > startY; j--) {
            res[i][j] = count++;
        }
        for(;i > startX; i--) {
            res[i][j] = count++;
        }

        // 更新起始位置
        startX++;
        startY++;

        // 更新offset
        offset += 2;
    }
    
    // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    if(n % 2 == 1) {
        res[mid][mid] = count;
    }
    return res
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值