4. 有序数组的平方
输入非递减顺序 排序的整数数组 ,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
- 暴力的解法
平方后排序,时间复杂度O(n+sort算法)
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) {
for(let i = 0; i < nums.length; i++) {
nums[i] *= nums[i]
}
nums.sort((a, b) => {return a-b}) // 不同浏览器实现的sort都不同,常见的有归并排序、快速排序和桶排序
return nums;
};
- 双指针法
数组有序,则平方后的最大值只可能在数组两端,可以考虑使用两个指针分别指在起始位置和末尾位置。
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) {
let left = 0, right = nums.length - 1;
let result = new Array(nums.length).fill(0);
let i = nums.length - 1;
while(i >= 0) {
if(nums[left] * nums[left] < nums[right] * nums[right]) {
result[i] = nums[right] * nums[right];
right--;
} else {
result[i] = nums[left] * nums[left];
left++;
}
i--;
}
return result;
};
改进后:
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) {
let left = 0, right = nums.length - 1;
let result = [];
while(right >= left) { // =是因为left=right时,仍然没有结束,还需要将此元素追加到新数组
const i = Math.abs(nums[left]);
const j = Math.abs(nums[right]);
if(i < j) {
result.unshift(j * j);
right--;
} else {
result.unshift(i * i);
left++;
}
}
return result;
};
5. 长度最小的子数组
- 暴力解法,因为使用了两个for循环时间复杂度为O(n2)
测试未通过,原因不明
/**
* @param {number} target
* @param {number[]} nums
* @return {number}
*/
var minSubArrayLen = function(target, nums) {
let result = Number.MAX_VALUE;
let sub_length = 0;
for(let i = 0; i < nums.length; i++) {
let sum = 0;
for(let j = i; j < nums.length; j++) {
sum += nums[j];
if(sum >= target) {
sub_length = j - i + 1;
result = result < sub_length ? result : sub_length;
break;
}
}
}
return result == Number.MAX_VALUE ? 0 : result;
};
- 滑动窗口
通过一个循环移动两个指针,具体来讲,循环移动右指针,判断sum是否满足条件移动左指针,时间复杂度O(n)。
/**
* @param {number} target
* @param {number[]} nums
* @return {number}
*/
var minSubArrayLen = function(target, nums) {
let result = Infinity;
let left = 0;
let right = 0; // 这样let left, right = 0赋值的语法是错的,ES6新增语法let [left, right] = [0, 0]是正确的
let sum = 0
while(right < nums.length) {
sum += nums[right];
while(sum >= target) {
let len = right - left + 1;
result = result < len ? result : len;
sum -= nums[left];
left++;
}
right++;
}
return result === Infinity ? 0 : result;
};
6. 绘制螺旋矩阵
通过offset控制,使用左闭右开的区间
/**
* @param {number} n
* @return {number[][]}
*/
var generateMatrix = function(n) {
let result = Array(n).fill().map(() => Array(n));// 创建二维数组
let loop = Math.floor(n/2); // n/2=1.5,控制画多少圈
let mid = Math.floor(n/2);
let offset = 1; // 控制每一层填充元素个数
let count = 1; // 每个位置的填充
let startX = startY = 0; // 起始位置
while(loop) {
let row = startX, col = startY;
for (; col < n - offset; col++) { //n - offset为每层填充的个数,此处为左闭右开,边界不做处理,故为<
result[row][col] = count++;
}
for (; row < n - offset; row++) {
result[row][col] = count++;
}
for (; col > startY; col--) {
result[row][col] = count++;
}
for (; row > startX; row--) {
result[row][col] = count++;
}
// 调整下一圈的位置等
startX++;
startY++;
offset += 1;
loop--;
}
if (n % 2 === 1) {
result[mid][mid] = count;
}
return result;
};