三道题,两道一开始都没做出来呜呜
977.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
最开始的思路:
先平方,后排序。都用js的内置方法。sort方法的时间复杂度不确定,ECMAScript不同版本可能使用不同的排序算法。
代码:
var sortedSquares = function (nums) {
// 先平方
// map方法时间复杂度是O(n)
nums = nums.map(x => x*x);
// 再排序,具体时间复杂度未知,但应该都大于O(n)
nums.sort((a,b)=> a-b);
return nums;
};
再考虑怎么才能让时间复杂度满足O(n),应该是两个指针,分别从前往后和从后往前,这样一共遍历一次数组,时间复杂度是O(n)。
代码:
var sortedSquares = function (nums) {
const len = nums.length;
// 先平方
// map方法时间复杂度是O(n)
nums = nums.map(x => x*x);
// 排序。双指针。并且原地不好实现,用另外一个数组用来存放结果。
let res = new Array(len);
let l = 0, r = len-1;
let n=len-1;
while(l<=r){
if(nums[l]<nums[r]){
res[n--]=nums[r--];
}else{
res[n--]=nums[l++];
}
}
return res;
};
209.长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其和 ≥ target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
一开始的思路,是暴力解法,即让每一个元素都作为首元素,然后寻找满足条件的子数组长度。超时
var minSubArrayLen = function (target, nums) {
// 思路:如果所有和<target,返回0。
let sum = nums.reduce((prev, cur) => prev + cur);
if (sum < target) return 0;
// 暴力解法
let res = Infinity;
for (let i = 0; i < nums.length; i++) {
// i是窗口的左边界。固定左边界,这是找一个满足要求的窗口的过程。
let j = i;
// j是窗口的右边界
let s = nums[i];
while (s < target && j < nums.length) {
j++;
s += nums[j];
}
if (s >= target) {
// 找到了一个满足要求的窗口
let len = j - i + 1;
res = res < len ? res : len;
}
}
return res==Infinity ? 0 : res;
};
滑动窗口没有AC。看了解析以后才知道要固定右边界,移动左边界。
滑动窗口:就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。一个for循环,索引表示的是滑动窗口的终止位置。滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
var minSubArrayLen = function (target, nums) {
// 滑动窗口来做,一个for循环,循环的是右边界。
let i=0;
let res = Infinity;
let s = 0;
let len;
for(let j=0; j<nums.length; j++){
s += nums[j];
while(s>=target){
// 满足条件了,记录一次长度
len = j-i+1;
res = res < len ? res : len;
// 滑动窗口的精髓:就在于此,固定右边界,不断缩小左边界。
s-=nums[i++];
}
}
return res===Infinity ? 0 : res;
};
59.螺旋矩阵II
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
示例 1:
输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]]
自己做没有AC。菜菜子···
本题是模拟数组的生成,关键是各种边界下标的处理。
var generateMatrix = function (n) {
// 模拟数组的生成过程
// 几圈
let loop = Math.floor(n/2);
let startX = 0, startY = 0;
let i=1; // i记录的是第几圈
let k=1; //填充的数值
let res = new Array(n).fill(0).map(x=>new Array(n).fill(0));
while(loop--){
// 每圈,都是上行(从左往右)-右列(从上往下)-下行(从右往左)-左列(从下往上)
// 每圈的起始坐标、终止坐标不一样
for(;startY<n-i;startY++){
res[startX][startY]=k++;
}
for(;startX<n-i;startX++){
res[startX][startY]=k++;
}
for(;startY>i-1;startY--){
res[startX][startY]=k++;
}
for(;startX>i-1;startX--){
res[startX][startY]=k++;
}
i++;
startX++;
startY++;
}
// 奇数,中间还剩一个空格没填
if(n%2){
res[startX][startY]=k;
}
return res;
};