Leetcode代码算法(数组) —— 有序数组的平方、长度最小的子数组、螺旋矩阵II

有序数组的平方

Leetcode题目链接

观察数组可以发现,数组里的数值的绝对值是先递减,到0后再递增的。此时可以使用双指针法,一个指针i从起始位置开始,另一个指针j从结束位置开始。比较两者的值,大的值放到新的结果集里面

代码如下: 

var sortedSquares = function (nums) {
  // 初始化双指针i和j,一个从起始开始,一个从结束开始
  let i = 0;
  let j = nums.length - 1;
  const newNums = []; // 新的结果集

  while (i <= j) {
    if (Math.abs(nums[i]) > Math.abs(nums[j])) {
      newNums.unshift(nums[i] * nums[i]);
      i++;
    } else {
      newNums.unshift(nums[j] * nums[j]);
      j--;
    }
  }
  return newNums;
};

长度最小的子数组

Leetcode题目链接

本题也是可以使用双指针的方式实现:下标i表示当前被检测数组的起始位置,下标j表示当前被检测数组的结束位置。由于j总是大于i,此时好像一个滑动窗口在原数组中滑动,因此也可以称为滑动窗口的解决办法。

我们先初始化一个min值表示当前最小的符合要求子数组的长度。如上图所示,如果滑动窗口的数组值大于target,则刷新min的值,然后j往右移动,否则i往左移动。

代码实现:

var minSubArrayLen = function (target, nums) {
  let min = Infinity;
  let i = 0;
  let sum = 0;

  for (let j = 0; j < nums.length; j++) {
    sum = sum + nums[j];
    while (sum >= target) {
      const currentLength = j - i + 1;
      min = Math.min(min, currentLength);

      sum = sum - nums[i];
      i++;
    }
  }

  return min === Infinity ? 0 : min;
};

螺旋矩阵II

Leetcode题目链接

本题的关键的思路是找到怎样循环,我们可以在一个循环里填充一圈,分别涉及到4条边:

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

有外向内一圈圈画下去。

至于边界问题,我们在代码中使用左闭右开的原则,如下图:

每一种颜色代表一条当前遍历的边。

代码如下:

var generateMatrix = function(n) {
  let startX = 0;
  let startY = 0;
  let offset = 0;
  let nums = [];
  let count = 1;

  for (let i = 0; i < n; i++) {
    nums.push([]);
  }

  let roundIndex = 0;
  
  while (roundIndex < Math.floor(n / 2)) {
    const edgeTotal = n - offset - 1;

    for (let i = startX; i < edgeTotal; i++) {
      nums[startX][i] = count;
      count++;
    }
    for (let i = startY; i < edgeTotal; i++) {
      nums[i][edgeTotal] = count;
      count++;
    }
    for (let i = edgeTotal; i > startX; i--) {
      nums[edgeTotal][i] = count;
      count++;
    }
    for (let i = edgeTotal; i > startY; i--) {
      nums[i][startX] = count;
      count++;
    }

    roundIndex++;
    startX++;
    startY++;
    offset++;
  }

  if (n % 2 === 1) {
    let middleIndex = Math.floor(n / 2);
    nums[middleIndex][middleIndex] = n * n;
  }
  
  return nums
};

数组类型算法的总结

在做一条数组的算法题前,可以先想想循环的边界:到底是用左闭右闭还是左闭右开?很多数据的问题都可以使用双指针的方式实现。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值