文档讲解:代码随想录
视频讲解:双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili
第二天,因为没有合理分配好时间,导致我很晚才开始写博客和复盘,下次得长记性了。
977.有序数组的平方
感受:看到题目时和多数人一样想的是直接用暴力解法,然后内置函数sort排个序输出就ok了。但最后时间复杂度为O(n + nlogn),理智告诉我不可以对自己太不负责任。。于是结合卡哥的提示再经过一些思考,这题用双指针法就不难了。我知道,难的是从不愿多动手。
思路:对于给定的已排序的数组而言,若将每个元素平方,则最大值只可能出现在数组两端,如[-10,5],平方后最大值在最左端。定义i、j指针分别指向数组的起始和终止位置,k来记录元素平方后位于新数组的位置,新数组我们定为result,用来存储按平方后的大小排列的元素。就有如下代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int k = nums.size() - 1;
vector<int> result(nums.size(), 0);
for(int i = 0, j = nums.size() - 1; i <= j;){
if(nums[i] * nums[i] > nums[j] * nums[j]){
result[k--] = nums[i] * nums[i];
i++;
}
else{
result[k--] = nums[j] * nums[j];
j--;
}
}
return result;
}
};
209.长度最小的子序列
感受:题不难,很好理解
思路:使用滑动窗口方法解决。窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT_MAX;
int sum = 0;
int sumlength = 0;
int start = 0;
for(int j = 0; j < nums.size(); j++){
sum += nums[j];
while(sum >= target){
sumlength = j - start + 1;
result = result > sumlength ? sumlength : result;
sum -= nums[start++];
}
}
return result == INT_MAX ? 0 : result;
}
};
59.螺旋矩阵
感受:这道题有点难,需要多看视频多理解。
思路:本题我们需要遵循二分查找里的循环不变量原则,即需要遵从一个边界条件如左闭右开这样从一而终。进而模拟出螺旋的过程。以下代码仍然遵从左闭右开原则:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n, 0));
int loop = n / 2;
int i,j;
int startx = 0,starty = 0;
int mid = n / 2;
int offset = 1;
int count = 1;
while(loop--){
i = startx;
j = starty;
for(j = starty; j < n - offset; j++){
res[startx][j] = count++;
}
for(i = startx;i < n - offset; i++){
res[i][j] = count++;
}
for(; j > starty; j--){
res[i][j] = count++;
}
for(; i > startx; i--){
res[i][j] = count++;
}
startx++;
starty++;
offset += 1;
}
if(n % 2){
res[mid][mid] = count;
}
return res;
}
};
总结: 今日用时3h,又是熬夜写代码的一天,计算机人哪有不疯的啊哈哈。