977.有序数组的平方
977.有序数组的平方
数组:非递减排序(增或者相等),有负数,将数组平方之后,非递减排好
双指针解法
首先含负数-->平方之后最大分布在两边,中间小-->分别从两边开始,谁大谁放入新数组:非递减排好
因为有时间复杂度O(n)限制,如果直接平方再快排,时间复杂度为O(nlog),所以不能快排
数组非递减表示:递增或者相等,定义两个指针
i从前,j从后,选平方后大的加入新数组,
因为题目要求得到的数组从小到大排序-->新数组下标从后往前放
类似归并排序的归并部分
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) { //双指针写法
let n = nums.length //先获取数组长度
let l = 0, r = n - 1, k = n - 1
let result = new Array(n).fill(0) //创建一个新数组装平方排好的数
while (l <= r) { //[]区间
let left = nums[l] * nums[l] //左边平方
let right = nums[r] * nums[r] //右边平方
if (left >= right) { //新数组从后往前谁大放谁
result[k--] = left
l++ //别忘记移动指针
} else {
result[k--] = right
r--
}
}
return result
};
209. 长度最小的子数组
209.长度最小的子数组
找数组里面,和 >= target 且长度最小的 连续子数组,返回长度,不存在返回 0
滑动窗口来解(双指针)
什么是滑动窗口:滑动的窗口
滑动窗口怎么实现呢?
首先定义两个指针i = 0起始位置,j = 0终止位置,j作为for循环索引去遍历数组(这样只要遍历一次),每移动一次求sum和,满足>= target条件时:
- 计算长度
length = j-i+1(比如1~10长度为10 = 10-1+1) ,如果比result小就更新最小值 i前移,sum减去被移出的,直到不满足>= target条件(因为如果 i 不移 j 就移了,得到数组的长度肯定会更大,不符合找最小值)j继续后移循环,直到数组结束
注意用while循环:因为每移除一个元素都可能产生满足 和>= target的数组,都要进行操作
/**
* @param {number} target
* @param {number[]} nums
* @return {number}
*/
var minSubArrayLen = function(target, nums) {
let i = 0; //起始位置
let sum = 0; //和
let len = 0; //窗口长度 子数组长
let result = Infinity; //result最终结果,Infinity无穷大,使能被小值更新
for (let j = 0; j < nums.length; j++) {
sum += nums[j]; //终止位置每移动一次加上新进来的
while (sum >= target) { //满足条件一直前移窗口
len = (j - i + 1) //算满足条件的数组长度
result = result < len ? result : len //用的小更新
sum -= nums[i] //移除窗口,减掉移除的
i++
}
}
return result === Infinity ? 0 : result //result没变:不存在符合的返回0
};
// 注意:初始化res设为Infinity,必须先减去sum值再前移i
注意:把result初始值设为Infinity无穷大
59.螺旋矩阵
循环不变量-->每边左闭右开[)
每圈都从startx,starty开始,每边都处理第一个不处理最后一个,下圈startx,starty都+1,
-
startx是控制左边往里收,offset是控制右边往里收,上面和下面同理 -
JS中
n/2直接得到小数,要取整用Math.floor()
/**
* @param {number} n
* @return {number[][]}
*/
var generateMatrix = function(n) {
let result = new Array(n).fill(0).map(() => new Array(n).fill(0)) //创建二维数组
let startx = 0, starty = 0; //每圈起始位置
let i = 0, j = 0; //遍历指针
let count = 1; //赋值
let loop = Math.floor(n/2); //循环几次,转一圈解决两行,奇数在最后中间元素单独处理
let offset = 1; //控制遍历长度
while (loop--) {
//左闭右开,遍历每圈的边
for (j = starty; j < n - offset; j++) {
result[startx][j] = count++
}
for (i = startx; i < n - offset; i++) {
//j == n-offset不变
result[i][j] = count++
}
for (; j > starty; j--) {
//i = n-offset不变 j向前移动
result[i][j] = count++
}
//j初始值不用变
for (; i > startx; i--) {
//j = starty-1不变,i向上移
result[i][j] = count++
}
offset++;
startx++;
starty++;
}
let mid = Math.floor(n/2)
if(n % 2){ //如果n是奇数,处理二维数组的中心
result[mid][mid] = count //count已经为加完之后的值
}
return result
};