数组:LeetCode977.有序数组的平方&209. 长度最小的子数组&59.螺旋矩阵~JS太酷啦🏃‍♂️

108 阅读3分钟

977.有序数组的平方

977.有序数组的平方 数组:非递减排序(增或者相等),有负数,将数组平方之后,非递减排好 image.png

双指针解法

首先含负数-->平方之后最大分布在两边,中间小-->分别从两边开始,谁大谁放入新数组:非递减排好 因为有时间复杂度O(n)限制,如果直接平方再快排,时间复杂度为O(nlog),所以不能快排 数组非递减表示:递增或者相等,定义两个指针 i从前,j从后,选平方后大的加入新数组, 因为题目要求得到的数组从小到大排序-->新数组下标从后往前放 类似归并排序的归并部分

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) { //双指针写法
    let n = nums.length //先获取数组长度
    let l = 0, r = n - 1, k = n - 1
    let result = new Array(n).fill(0) //创建一个新数组装平方排好的数
    while (l <= r) { //[]区间
        let left = nums[l] * nums[l] //左边平方
        let right = nums[r] * nums[r] //右边平方
        if (left >= right) { //新数组从后往前谁大放谁
            result[k--] = left
            l++ //别忘记移动指针
        } else {
            result[k--] = right
            r--
        }
    }
    return result
};

209. 长度最小的子数组

209.长度最小的子数组 找数组里面,>= target 且长度最小的 连续子数组,返回长度,不存在返回 0

滑动窗口来解(双指针)

什么是滑动窗口:滑动的窗口

滑动窗口怎么实现呢? 首先定义两个指针i = 0起始位置,j = 0终止位置j作为for循环索引去遍历数组(这样只要遍历一次),每移动一次求sum和,满足>= target条件时:

  • 计算长度length = j-i+1(比如1~10长度为10 = 10-1+1) ,如果比result小就更新最小值
  • i前移,sum减去被移出的,直到不满足>= target条件(因为如果 i 不移 j 就移了,得到数组的长度肯定会更大,不符合找最小值)
  • j继续后移循环,直到数组结束

注意用while循环:因为每移除一个元素都可能产生满足 和>= target的数组,都要进行操作

/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function(target, nums) {
    let i = 0; //起始位置
    let sum = 0; //和
    let len = 0; //窗口长度 子数组长
    let result = Infinity; //result最终结果,Infinity无穷大,使能被小值更新
    for (let j = 0; j < nums.length; j++) {
        sum += nums[j]; //终止位置每移动一次加上新进来的
        while (sum >= target) { //满足条件一直前移窗口
            len = (j - i + 1) //算满足条件的数组长度
            result = result < len ? result : len //用的小更新
            sum -= nums[i] //移除窗口,减掉移除的
            i++
        }
    }
    return result === Infinity ? 0 : result //result没变:不存在符合的返回0
};
// 注意:初始化res设为Infinity,必须先减去sum值再前移i

注意:把result初始值设为Infinity无穷大

59.螺旋矩阵

59. 螺旋矩阵 II image.png

循环不变量-->每边左闭右开[)

每圈都从startx,starty开始,每边都处理第一个不处理最后一个,下圈startx,starty都+1,

  • startx是控制左边往里收,offset是控制右边往里收,上面和下面同理

  • JS中n/2直接得到小数,要取整用Math.floor()

/**
 * @param {number} n
 * @return {number[][]}
 */
var generateMatrix = function(n) {
  let result = new Array(n).fill(0).map(() => new Array(n).fill(0)) //创建二维数组
  let startx = 0, starty = 0; //每圈起始位置
  let i = 0, j = 0; //遍历指针
  let count = 1; //赋值
  let loop = Math.floor(n/2); //循环几次,转一圈解决两行,奇数在最后中间元素单独处理
  let offset = 1; //控制遍历长度
  while (loop--) {
    //左闭右开,遍历每圈的边
    for (j = starty; j < n - offset; j++) {
      result[startx][j] = count++
    }
    for (i = startx; i < n - offset; i++) {
      //j == n-offset不变
      result[i][j] = count++
    }
    for (; j > starty; j--) {
      //i = n-offset不变 j向前移动
      result[i][j] = count++
    }
    //j初始值不用变
    for (; i > startx; i--) {
      //j = starty-1不变,i向上移
      result[i][j] = count++
    }
    offset++; 
    startx++;
    starty++;
  }
  let mid = Math.floor(n/2)
  if(n % 2){ //如果n是奇数,处理二维数组的中心
    result[mid][mid] = count //count已经为加完之后的值
  }
  return result
};