没 有明确的学习目的就不要在正在做一件事的时候打开B站,因为真的会迷失一段时间,看一堆没有意义的东西!!!
然后再回来做继续做的事就感觉脑袋被掏空。
某种意义上我称B站为我的大毒草!!
今天卡哥给留了三道题。。。
严重怀疑我这菜鸡会不会完成
题目链接
自己思路是一样的,就是对容器毫无了解,之后用sort函数的时候不知道容器该咋用
在这里新学了容器的begin()和end()两个函数
又得重新复习一下sort
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i=0;i<nums.size();i++){
nums[i]=nums[i]*nums[i];
}
sort(nums.begin(),nums.end());
return nums;
}
};
理论:
你平方之后,有些负数(在数组最前端)可能会变大,所以最值都会出现在数组两端,用两个指针,分别从两两边向中间走,选出更大的元素然后填入新的数组中,(有点类似于快排啊)
容器开辟数组的代码:vector
可真得是学习学习容器了。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i=0;i<nums.size();i++){
nums[i]=nums[i]*nums[i];
}
int k=nums.size()-1;
vector<int> result(nums.size(), 0);
for(int i=0,j=nums.size()-1;i<=j;){
//注意此处的for循环的第二个分号别忘了。
//同时也要注意是i<=j,别忘了“=”
//第三出可以没有,可以在函数体中体现
if(nums[i]<=nums[j])result[k--]=nums[j--];
else result[k--]=nums[i++];
}
return result;
}
};
又重新敲了一遍,明天敲新的算法之前再复习一遍
题目链接
首先注意审题,是找最短的连续的子数组,满足其元素之和大于所给target
思路:
先找一个变量存要找的子数组的长度,一开始赋值为0
int sublength=0;
要找一个子数组的话,就得有始有终,然后寻找下一个子数组,有点像kmp那个最基础版。
所以你得有一个头指针,用于定位子数组开头,然后寻找每个新的子数组之前得往右移一个,
尾指针,就是不断从头指针的位置往后加数,直到这个子数组的所有元素之和已经大于target就开始停止,若其长度已经比已经所找到的还要短,那么就更新sublength。
第一次执行,忘了一个问题,就是length不能一开始就赋值0,
而且break放if条件之外了,呵呵,直接一工作即躺平。
错误代码示例
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum=0,sublength=0,length=0;
for(int i=0;i<nums.size();i++){
sum=0;
for(int j=i;j<nums.size();j++){
sum+=nums[j];
if(sum>=target){length=j-i+1;
sublength=sublength<=length?sublength:length;
}
break;//
}
}
return sublength;
}
};
最后还比较个啥,0肯定最小啊
从卡哥代码上抄了个最大赋值INT32_MAX
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum=0,sublength=INT32_MAX,length=0;
for(int i=0;i<nums.size();i++){
sum=0;
for(int j=i;j<nums.size();j++){
sum+=nums[j];
if(sum>=target){length=j-i+1;
sublength=sublength<length?sublength:length;
break;
}
}
}
return sublength==INT32_MAX?0:sublength;
}
};
暴力解超出时间限制了。时间复杂度为O(n^2)。
可我连暴力解也得好好想想。。。
卡哥滑动窗口教程
看图解有点像kmp字符串比对
我感觉像以前以后俩指针后面那个指针不断往后移动,如果子数组元素之和>=target,那么就已经找到了当前最短的子数组,然后前指针往后移一位,接着寻找新的子数组。
这里有个注意事项,你前指针往后移动了一个的时候,后指针是没有动的,所以,此处就会涉及一个sum=sum-nums[i++];
可以直接算出新的子数组和,而不需要再用一个for遍历新的子数组了
后面卡哥说滑动窗口也是双指针的一种,果然我的感觉没有出错~
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum=0,sublength=INT32_MAX,length=0,i=0;
for(int j=0;j<nums.size();j++){
sum+=nums[j];
while(sum>=target){length=j-i+1;
sublength=sublength<length?sublength:length;
sum-=nums[i++];//找到满足条件的子数组后变更
//这步让双指针看起来更像滑动窗口。
}
}
return sublength==INT32_MAX?0:sublength;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
线性关系不是平方关系,
不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)
(我就纳闷之前任务清单上写的那个拓展题在哪,今天终于看见了。。。)
我再敲一遍。
一看题,要不是我花钱了,这题我没有什么理由自己去敲。
犹如自己花钱给自己开工资的感觉。。。
循环不变量原则,昨天没学,今天补上,看着那个解说就很复杂的样子我很头疼。
这代码又敲了半天,我只能说,我还是前一天提前预习,多完成点任务比较好,当天完成有点有压迫感。
就是对边界处理要统一,比如你每个循环中要始终坚持左开右闭或左闭右开这一种原则就可
下面又来细节讲一下什么是左闭右开,就是只处理第一个边界点,而不处理最后一个边界点。
如何用容器定义一个二维数组vector
还有涉及一个转几圈怎么确定呢? n/2圈,如果n是奇数,则中间个会留下来,要另外赋值,赋最大的那个值n*n
可能思路并不是最难理解的,是需要初始化几个变量,每个变量用来干啥比较难想。
第一次提交犯了两个错误,count一开始是从1 开始赋值的
有种顺时针给九宫格农田播种的感觉。。。
再一个就是在每轮的每边循环的过程中,就第一次是行坐标是用常量startx,紧接着
到下一个边用的就是遍历上次的边的列坐标j而不是starty了
而到了第三条边数组遍历摆脱了startx和starty
难点就是那些个变量,该怎么想,以及循环的过程中的边界处理与指针选择
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>>res(n,vector<int>(n,0));
int startx=0,starty=0;
int mid=n/2;
int count=1;
int loop=n/2;//规定所转的圈数(是否还要继续循环的条件)
int offset=1;//用来限制每圈的边的长度(越往内圈你要走的边的长度越来越少)
int i,j;
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++;
}
//遍历完所有圈之后,如果是奇数,那得给中间赋值。
if(n%2){
res[mid][mid]=count;
}
return res;
}
};
咳,新任务都发出来了我刚给这仨题搞完,对前途抱有一阵渺茫啊。