数组| 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;
}
};