今日任务:day 2 第一章数组
题目:力扣
考点:双指针
如果采用传统思路(暴力解法),先求平方再排序,则取决于快排的时间复杂度,为O(n + nlogn)
动图-https://code-thinking.cdn.bcebos.com/gifs/977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.gif
建立新数组result,用k--,是因为指针i,j是从大到小的顺序去找,而新数组要求从小到大
class Solution {
public:
vector sortedSquares(vector& nums) {
int k = nums.size() - 1;
vector result(nums.size(), 0); // 新建容器,有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++;
k--;
}
else{
result[k] = nums[j] * nums[j];
j--;
k--;
}
}
return result;
}
};
题目:力扣
考点:滑动窗口(还是双指针)
看文字难理解,建议看视频讲解
思路动图:https://code-thinking.cdn.bcebos.com/gifs/209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.gif
难点1:for循环中的变量指向的是滑动窗口的初始位置还是终止位置?
答:如果指向初始位置,那么终止位置只能从左到右逐渐遍历,形成当前初始位置所对应的集合,那思想上与暴力解法是一样的,所以其指向的是滑动窗口的终止位置。
所以本题的难点2是如何移动滑动窗口的初始位置
class Solution {
public:
int minSubArrayLen(int target, vector& nums) {
int i = 0;
int sum = 0;
int len = 0;
int result = nums.size() + 1;
for(int j=0; j < nums.size(); j++){
sum += nums[j];
while(sum >= target){
len = j - i + 1; //因为len可能会由小变大,但我们要的是最短的长度,所以要用新变量保存
result = len < result ? len : result;
sum -= nums[i];
i++;
}
}
return result == nums.size()+1 ? 0 : result; //为了满足没有子集符合时需返回0的情况
}
};
问题:自己写时遇到的问题就是有了len问什么还要有result?
答:因为滑动窗口的长度len是不断变化的,而要把最短的保留下来,所以要加个变量result
最后一行是为了满足没有子集符合时需返回0的情况
问题:为什么有两个循环却是O(n)
答:因为初始位置在随着终止位置向前移动,而不是把所有的遍历了一遍,没有做重复性工作
题目:力扣
面试出现频率较高,没有什么算法,主要就是推理过程
思路:统一左闭右开、循环不变量
class Solution {
public:
vector> generateMatrix(int n) {
vector> res(n, vector(n,0));
int xstart = 0, ystart = 0;
int i = 0, j = 0;
int loop = n / 2; //圈数
int s = 1; //边界剩余
int count = 1;
while(loop--){
i = xstart;
j = ystart;
for(j=ystart; jystart; j--)
res[i][j] = count++;
for(; i>xstart; i--)
res[i][j] = count++;
xstart++;
ystart++;
s++;
}
if(n % 2 == 1)
res[n/2][n/2] = count; //如果输入是1的话,前面就不会进循环,所以用i,j表示不合适
return res;
}
};
二分法、双指针
基本必考,不要轻敌
704.二分查找:二分法,左闭右闭(更习惯)和左闭右开两种写法,left=0 right=nums.size()-1
27.移除元素:双指针法,快指针和慢指针,通向出发,快指针用于找目标元素,慢指针用于确定新数组的位置索引
977.有序数组的平方:双指针法,两指针相向而行,均是为了找平方较大的值,从大到小;新建数组,索引逐渐递减,从而实现从小到大
209.长度最小的子数组:滑动窗口法(双指针),两指针同向而行,形成滑动窗口,遍历的是终止指针,起始指针随着终止指针向前,注意求的是窗口长度变化过程中的最小值,所以要单独拿个变量保存
59.螺旋矩阵:不涉及算法,单纯模拟行为,考察代码掌控能力。利用循环不变量原则,一圈一圈的执行,每一圈分成4个方向,均采用左闭右开。
写数组时,一般用vector容器较多,求元素数量可以用.size()