977.有序数组的平方
第一想法
先把每个数平方了,再对新数组排序
JS代码如下:
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) {
let num = [];
let i = 0,j = 0, n = 0;
for(i = 0; i < nums.length; i++){
num[i] = nums[i] * nums[i]
}
for(i = 0; i < num.length; i++){
for(j = 0; j < num.length - i - 1; j++){
if(num[j] > num[j+1]){
n = num[j+1];
num[j+1] = num[j];
num[j] = n;
}
}
}
return num;
};
这里使用了冒泡法排序,时间复杂度为O(N+NlogN)
思路
其实数组本身就是有序的,所以最大值一定在两端,不可能是中间
即,问题可以被转化为,最大的值是在左边还是右边,第二大的值是在左边还是右边,以此类推
因此,可以使用左右两个指针对数组进行操作
JS 代码如下:
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) {
let left = 0, n = nums.length - 1;
let right = n, i = n;
let num = new Array(n).fill(0);
while(left <= right){
if(nums[left]*nums[left] >= nums[right]*nums[right]){
num[i--] = nums[left]*nums[left];
left++;
}else if(nums[left]*nums[left] < nums[right]*nums[right]){
num[i--] = nums[right]*nums[right];
right--;
}
}
return num;
};
总结
js的数组的初始化没写出来,尴尬
这道题注意是依次把最大值找出来,所以,需要先建立一个全是0的数组
再对数组进行赋值
209.长度最小的子数组
第一想法
两个循环,不断寻找符合条件的子序列
显然,暴力解法的复杂度实在太高了
思路
滑动窗口思想
不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
for循环中的参数是滑动窗口的终止位置
for (int j = 0; j < nums.size(); j++) {
sum += nums[j];
// 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
while (sum >= s) {
subLength = (j - i + 1); // 取子序列的长度
result = result < subLength ? result : subLength;
sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
}
滑动窗口的精妙之处在于此,先通过一点点增加终止位置的值,找到一个满足条件的范围,这个范围作为窗口
然后对窗口进行操作,如果元素和大于target则起始位置左移
如果元素和小于target则终止位置右移
判断每次满足条件的窗口的大小是不是当前最小值,如果是的话,可以更新
JS代码如下:
/**
* @param {number} target
* @param {number[]} nums
* @return {number}
*/
var minSubArrayLen = function(target, nums) {
let result = Infinity, i = 0, j = 0, sum = 0, len = 0;
for(j = 0; j < nums.length; j++){
sum += nums[j];
while(sum >= target){
len = j - i + 1;
result = len < result? len : result;
sum -= nums[i++]
}
}
return result == Infinity? 0 : result;
};
总结
这一题的思路非常重要,精妙之处在于遍历终止位置,调节起始位置来得出窗口的大小
另外,这一题需要细心
在写的过程中,sum -= nums[i++]这一步漏掉了
窗口缩小时不要忘记sum要减去对应的值!
59.螺旋矩阵II
第一想法
完全不会,不知道怎么下手
思路
这里全部统一按照左闭右开来写(参照卡哥的图)
为了方便,设置好每次循环一圈的初始位置:startx 和 starty,每循环完一圈初始位置都要+1
同时,每一圈的终点位置相比于上一圈也会减一,因此设置变量offset
最后,需要考虑的是n是奇数还是偶数,循环的圈数loop = n/2
如果n是奇数,则循环结束后最中间的点还没有被赋值,需要另外赋值
JS代码如下:
/**
* @param {number} n
* @return {number[][]}
*/
var generateMatrix = function(n) {
let res = new Array(n).fill(0).map(()=>new Array(n).fill(0));
let i = 0, j = 0, loop = 0, num = 1;
let startx = 0, starty = 0, offset = 1,mid = parseInt(n/2);
loop = parseInt(n/2);
while(loop--){
// 设置好循环的初始位置和终止位置
for(j = starty; j < n - offset; j++){
res[startx][j] = num++;
}
for(i = startx; i < n - offset; i++){
res[i][j] = num++;
}
for(;j > starty; j--){
res[i][j] = num++;
}
for(;i > startx; i--){
res[i][j] = num++;
}
// 循环完一圈,下一圈初始位置+1,终止位置-1
starty++;
startx++;
offset++;
}
// 如果是奇数,最后给中间点赋值
if(n % 2){
res[mid][mid] = num;
}
return res;
};
总结
二维数组这道题写了好久,一开始没有用初始位置和终止位置以及offset这几个变量,导致整体思路比较乱
理清楚每次循环的初始位置和终止位置,就会清楚的多
另外,对于最后给中间点赋值这一步,一开始是直接res[i][j] = num;
因为循环结束后,i和j的位置刚好是中间点
但是这里忽略了一个问题,作用域外面是无法访问作用域内部的变量的,因此,这里的`res[i][j]实际上是res[0][0]
导致结果出现错误