977. 有序数组的平方
题目描述:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
初始解题思路
解题语言使用的是JavaScript,第一时间想到的操作:
var sortedSquares = function(nums) {
let arr = nums.map(val => Math.abs(val)).sort((a,b) => a-b).map(val => val*val)
return arr
};
题解思路:左右双指针法
由于数组按非递减顺序排列,且返回值为每个数的平方。通过观察测试用例可以得到左右两边的绝对值最大,向中间依次递减。
设置左右两个指针分别指向nums数组的首尾,比较其绝对值大小,将大的那一个取平方,放入结果数组;移动指针,依次进行比较,直到 left > right为止
var sortedSquares = function(nums) {
let len = nums.length
let res = Array(len)
let p = len-1
for(let i=0,j=len-1;i<=j;){
if(Math.abs(nums[i])>Math.abs(nums[j])){
res[p] = nums[i]*nums[i]
i++
}else{
res[p] = nums[j]*nums[j]
j--
}
p--
}
return res
};
209. 长度最小的子数组
题目描述:给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
初始解题思路:暴力双循环
暴力双循环,依次求取以s[i]开头的满足target条件的子数组,取最小长度进行比较。
var minSubArrayLen = function(target, nums) {
let subLength = 0
let minLen = Number.MAX_SAFE_INTEGER
let sum
for(let i= 0;i<nums.length;i++){
sum = 0
for(let j=i; j<nums.length; j++){
sum += nums[j]
if(sum >= target){
subLength = j - i + 1
minLen = Math.min(minLen,subLength)
break
}
}
}
if(minLen !== Number.MAX_SAFE_INTEGER){
return minLen
}else{
return 0
}
};
更优思路:滑动窗口法
滑动窗口:不断调节子数组的起始位置和结束位置,获取想要的子数组,如同一个窗口在数组上移动,展现给我们需要的子数组。
窗口的起始位置:当前窗口值大于 target, 窗口的起始位置需要向后移
窗口的结束位置:窗口的结束位置遍历到数组末尾时,相应的循环结束
var minSubArrayLen = function(target, nums) {
let res = Number.MAX_SAFE_INTEGER
let sum = 0
let start = 0
let subLength = 0
for(let end = 0; end<nums.length;end++){
//未满足target条件时,移动结束位置,累加 sum
sum += nums[end]
while(sum >= target){
subLength = end - start + 1
res = Math.min(res,subLength)
// 当子数组满足target 条件时,滑动窗口的起始位置移动
sum -= nums[start]
start ++
}
}
return res==Number.MAX_SAFE_INTEGER ? 0 : res
};
59. 螺旋矩阵 II
题目描述:给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
初始解法:由 [0,0] 一直向内循环
设定left top bottom right 四个边界值,依次向内进行顺时针螺旋,一次到底。
var generateMatrix = function(n) {
// let matrix = Array(n).fill(Array(n))
let matrix = Array(n).fill().map(item => new Array(n))
let [left,right,top,bottom] = [0,n-1,0,n-1]
let num = 1
while(num<=n*n){
for(let i=left;i<=right;i++){
matrix[top][i] = num
num ++
}
top ++
if(top > bottom) break
for(let i=top;i<=bottom;i++){
matrix[i][right] = num
num ++
}
right --
if(left > right) break
for(let i=right;i>=left;i--){
matrix[bottom][i] = num
num ++
}
bottom --
if(top > bottom) break
for(let i=bottom;i>=top;i--){
matrix[i][left] = num
num ++
}
left ++
if(left > right){
break
}
}
return matrix
// console.log(matrix)
};
其他解法
分圈逐层填满矩阵:
将矩阵由外到内分成若干层,每一层由四个相同大小的左闭右开区间组成。
var generateMatrix = function(n) {
let startX = 0
let startY = 0
let loop = Math.floor(n/2)
let mid = Math.floor(n/2)
let offset = 1
let num = 1
let res = new Array(n).fill().map(() => Array(n))
while(loop--){
let row = startX
let col = startY
for(; col < startY+n - offset;col++){
res[row][col] = num++
}
for(; row < startX + n - offset ; row++){
res[row][col] = num++
}
for(; col > startY ; col --){
res[row][col] = num ++
}
for(; row > startX ; row --){
res[row][col] = num ++
}
startY++
startX++
offset += 2
}
if( n%2 ==1){
res[mid][mid] = num
}
return res
};