数组| 977.有序数组的平方 、 209.长度最小的子数组、 59.螺旋矩阵II

📋 目录

  • 977.有序数组的平方
  • 209.长度最小的子数组
  • 59.螺旋矩阵II

 977.有序数组的平方

1.解题思路

  • 暴力解法

       直接数组平方,然后排序。

  • 双指针解法
原数组有序,并且存在负数,则平方后的最大值在两边,并且不确定是在哪一边,由此可以考虑双指针的方法。
定义的两个指针分别:
i:指向起始位置的下标,
j:指向终止位置的下标。
新数组里面:
k:指向新数组的终止位置的下标。
跳出循环的条件就是当 i<=j,取等于是在最后一个元素,i和j同时取到,如果没有等于就会漏掉最后一个元素。

💻2.代码

      暴力解法

// 暴力解法
/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function (nums) {
  // 创建一个新数组
  let res = [];
  for (let i = 0; i < nums.length; i++) {
    // 平方后添加到新数组
    res.push(nums[i] ** 2);
  }
  // 排序
  res.sort((a, b) => a - b);
  //   返回
  return res;
};

 双指针法

// 双指针方法
/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function (nums) {
  let res = [];
  let k = nums.length - 1;
  //   定义两个指针
  let i = 0,
    j = nums.length - 1;
  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;
};

😃 知识点补充: for循环和while的循环的使用:循环次数已知,使用for;未知次数或者是条件循环使用while。


209.长度最小的子数组

1.解题思路

  • 暴力解法
    两个for循环,发现目标子序列,就取子序列,并且跟已经存在的子序列长度进行比较,选择较小的那个长度。
  • 滑动窗口解法

把数组当成队列,元素一个一个的进去,当这个子数组的元素之和大于或者等于target,此时记录这个子序列的长度,同时将这个长度和之前已有的长度进行比较,得到二者最小值。然后队列最前面的元素出队,后面增加一个,再次比较之和。重复之前的步骤直到队列为空。

💻 2.代码

        暴力解法

/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
// 暴力解法
var minSubArrayLen = function (target, nums) {
  let res = Number.MAX_VALUE;
  console.log(Number.MAX_VALUE, "???");

  let n = nums.length;

  let subLength = 0; //子序列长度

  for (let i = 0; i < n; i++) {
    //子序列的起点为i
    let sum = 0;

    for (let j = i; j < n; j++) {
      //子序列的终点j
      sum += nums[j];

      if (sum >= target) {
        //超过target,就更新res
        subLength = j - i + 1; //子序列的新长度
        res = res < subLength ? res : subLength;
        break; //一旦符合条件就退出
      }
    }
  }
  //   Number.MAX_VALUE = 1.7976931348623157e+308,表示最大的数。res没有被赋值就为0
  return res === Number.MAX_VALUE ? 0 : res;
};
// console.log(minSubArrayLen(7, [2, 3, 1, 2, 4, 3]));

       滑动窗口解法

// 滑动窗口法
var minSubArrayLen = function (target, nums) {
  let start, end;
  start = end = 0;
  let sum = 0;
  let n = nums.length; //所给数组的长度
  let ans = Infinity; //超过最大数的值,失去其实际值
  while (end < n) {
    //窗口的结束位置小于数组长度
    sum += nums[end]; //窗口所包含数字之和
    while (sum >= target) {
      ans = Math.min(ans, end - start + 1);
      sum -= nums[start]; //窗口朝前移动,所以现在的和要减去现在窗口的start所在的值
      start++; //初始位置的指针朝前走
    }
    end++;
  }
  return ans === Infinity ? 0 : ans;
};
console.log(minSubArrayLen(7, [2, 3, 1, 2, 4, 3]));

 

59.螺旋矩阵II

1.解题思路

  • 确定边界,遵循循环不变量原则,确定每一次的区间都是左闭右开。
  • 判断n是不是奇数,n%2=1则是奇数,此时需要给最中间的位置赋值。
  • 判断旋转的圈数,n/2,向下取整。

💻 2.代码

var generateMatrix = function (n) {
  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 row = startX,
      col = startY;
    // 从左往右,左开右闭
    for (; col < startY + n - offSet; col++) {
      res[row][col] = count++;
    }
    //右列,从上往下
    for (; row < startX + n - offSet; row++) {
      res[row][col] = count++;
    }
    //下行,从右往左
    for (; col > startY; col--) {
      res[row][col] = count++;
    }
    //左列,从下往上
    for (; row > startX; row--) {
      res[row][col] = count++;
    }
    // 更新起始位置
    startX++;
    startY++;

    //更新offSet
    offSet += 2;

    if (n % 2 == 1) {
      res[mid][mid] = count++;
    }
    return res;
  }
};

  

 

posted @ 2023-04-20 22:59  karen哈哈哈  阅读(18)  评论(0编辑  收藏  举报