我正在参加「掘金·启航计划」
977.有序数组的平方
自己看到题目的第一想法
第一想法就是遍历这个数组,平方后再进行排序。正好js有内置的排序方法,十分的方便。
var sortedSquares = function(nums) {
for(let i = 0;i < nums.length;i++) {
nums[i] *= nums[i]
}
nums.sort((a,b) => {return a - b})
return nums
};
看完代码随想录之后的想法
发现还可以使用双指针来解这道题。平方后的数组不是有序的因为负数平方后可能会变得比正数大。这样数组两边的数平方后可能会变最大。
所以可以通过双指针分别指向数组的开头和末尾,通过比较得出比较大的数,再新建一个数组将大数存入,如下所示:
var sortedSquares = function(nums) {
let i = 0,j = nums.length - 1,k = nums.length - 1
let arr = new Array(nums.length).fill(0)
while(i <= j) {
let left = nums[i] * nums[i]
let right = nums[j] * nums[j]
if(left < right) {
arr[k--] = right
j--
} else {
arr[k--] = left
i++
}
}
return arr
};
自己实现过程中遇到哪些困难
对于双指针这种解法,通过动图可以理解函数的主要逻辑,但是在函数循环条件那里有些犹豫。什么时候结束,最后一个数如何放入数组中。这是需要仔细考虑的地方。
209.长度最小的子数组
自己看到题目的第一想法
首先的想法就是找出所有的可能比较大小。
这个就不用暴力的方法了,虽然可以解出来,但是时间复杂度很高。
看完代码随想录之后的想法
使用滑动窗口的方式解题,首先利用双指针,右面的指针不断向后,计算和,直到和大于或等于target。
和大于或等于target时需要左面的指针向后,也就是窗口收缩。使用一个变量记录当前最小的窗口长度。重复这个过程。
var minSubArrayLen = function(target, nums) {
let len = nums.length
let l = r = sum = 0
let res = len + 1
while(r < len) {
sum += nums[r++]
while(sum >=target) {
res = res < r - l ? res : r - l
sum -= nums[l++]
}
}
return res > len ? 0 : res
};
自己实现过程中遇到哪些困难
窗口收缩时同时要记录窗口的大小。
59.螺旋矩阵
自己看到题目的第一想法
没想法,哈哈,有点转不过来就去看题解了。
看完代码随想录之后的想法
看过题解视频,自己又画了几种情况后,渐渐有些理解。转的圈数与n有关,为 Math.floor(n / 2),其中如果n为奇数,最中间有一个格子没有转到,需要单独处理。也就是需要中间的格子的位置,是res[mid][mid]。
接下来就是每次循环,为了简化循环最好循环不变量,这里我们规定循环为左闭右开。
图有点丑不要介意,每个小循环为一个颜色,右侧为开区间。这样可以控制循环。
var generateMatrix = function(n) {
let startX = 0,startY = 0,offset = 1,num = 1
let count = Math.floor(n / 2) // 旋转圈数
let mid = Math.floor(n /2) // 奇数的中间位置
let res = new Array(n).fill(0).map(() => new Array(n).fill(0)) // 二维数组
while(count--) {
let i = startX // 行的起始位置
let j = startY // 列的起始位置
for(;j < n - offset;j++) {
res[startX][j] = num++
}
for(;i < n - offset;i++) {
res[i][j] = num++
}
for(;j > startY;j--) {
res[i][j] = num++
}
for(;i > startX;i--) [
res[i][j] = num++
]
startX++ // 起始位置加一
startY++
offset++
}
if(n % 2) {
res[mid][mid] = num
}
return res
};
自己实现过程中遇到哪些困难
看过视频后自信满满开始写代码,一执行错了,呜呜,开始debug。
看出错的地方就知道从右到左和从下到上两个过程没有问题。一顿排查发现自己数组列写错了。res[i][startX] = num++,应该是res[i][j] = num++
数组总结
今天结束了数组的学习,进行数组的总结:
数组是存放在连续内存空间上的相同类型数据的集合,由于数组存放在连续内存空间的特性,删除、增加元素的时候,需要移动其他元素的位置。例如27.移除元素,并不是简单的根据索引删除元素,需要使用后面的元素覆盖被删除的元素。
如果数组是不重复的并且有序(也可以先进行排序),查找元素的时候就应该考虑二分法。进行二分法的时候要坚持对区间的定义,比如一直坚持左闭右开或左闭右闭。考虑数据在定好的区间中是否有意义。
数组的题也常常可以用双指针方法实现,可以有效降低复杂度。
对于滑动窗口这类题,需要理解窗口的移动,确定窗口的起始位置。