有序数组的平方
观察数组可以发现,数组里的数值的绝对值是先递减,到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;
};
长度最小的子数组
本题也是可以使用双指针的方式实现:下标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
本题的关键的思路是找到怎样循环,我们可以在一个循环里填充一圈,分别涉及到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
};
数组类型算法的总结
在做一条数组的算法题前,可以先想想循环的边界:到底是用左闭右闭还是左闭右开?很多数据的问题都可以使用双指针的方式实现。
872





