题目:977.有序数组的平方
思路:
first. for循环,平方 ,然后sort排序, 提交通过 啊哈~|但时间复杂度大 O(n + nlogn), ->O(nlogn)的时间复杂度,题目进阶要求时间复杂度为 O(n)
second. 双指针。题目为有序数组,包含负数,则平方后,最大值在数组的两头,则使用双指针进行,
两个比较大小,大的存入新数组,进行从大到小、从后往前存入新数组。
时间复杂度为O(n)
坑:
题目是 有序 数组 且可以使用 额外的 内存空间,和之前做过的题目区分开啊
补充:
排序函数sort(begin,end,cmp):
- 根据数量级不同,自动选择合适的排序方法(快排,堆排等)
- cmp可省略,默认是从小到大排序,从大到小则将cmp换成 greater<类型>()
- begin 为指向数组第一个元素的指针,end 为指向数组 尾后 的指针 (最后一个元素的下一个位置)
- 头文件要包含
#include<algorithm>
- 可以根据需求进行自定义排序cmp
题目:209.长度最小的子数组
思路:
看随想录的提示
1.暴力法
两层for循环(i,j),每次循环从第i个元素开始,往后,循环依次累加,寻找符合条件的子数组,第二层循环的起始条件是j=i
一个for循环表示数组的起始位置,一个for表示数组的终止位置。
时间复杂度:O(n^2)
空间复杂度:O(1)
2.采用滑动窗口
滑动窗口,也是双指针的思路 ,主要明确,两个指针指向的含义是什么
本题,暴力法是两层for循环,一个for循环表示数组的起始位置,一个for表示数组的终止位置。
那么采用双指针i,j,且时间复杂度要求为O(n)的情况下,表示循环遍历的j指针,指向终止位置
两个指针之间的数组就是最求的子数组s,随着j的后移,s的值总和满足大于target则记下子数组个数len,
之后i后移,看缩减后的子数组s是否还>target,大于则更新len值
滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。
时间复杂度:O(n) 解释:时间复杂度,基本操作的执行次数,每个元素被执行两次,所以是 2 × n 也就是O(n)
空间复杂度:O(1)
坑:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
//滑动窗口
int sum=0; //记录子数组总和
int len=0;// 记录子数组长度
int m=nums.size()+1; //记录子数组最小长度 错误 ,初始值应设定为一个较大的值,m=INT32_MAX
int i=0;
for(int j=0;j<nums.size();j++){
sum+=nums[j];
while(sum>=target){ //错误 不是if 是while ,持续判断,滑动窗口
len=j-i+1; //错误每次都更新len,没设置保存最小长度的变量
m=len<m?len:m;
sum-=nums[i]; //这两步可以简化为一步 i++的特性,sum-=nums[i++]
i++;
}
}
return m==nums.size()+1?0:m; //判断m的值是否改变,错误 忽略 没有符合条件的情况,返回值为0
}
};
补充:
问号运算符 <表达式1>?<表达式2>:<表达式3> fg: result=a>b? a:b;
题目:59.螺旋矩阵Ⅱ
思路:
视频解析
显然是个循环, 循环就要坚持 循环不变量
循环不变量是 每条边的处理规则 ,z转一圈为一次循环,然后这个循环次数是 n/2
想不出来,B站视频大概懂了,但是代码有些困难,看的力扣上Krahets大神的题解矩阵解释图
每次循环的起始位置和终止位置都不是固定的,所以设为变量
理解转一圈是一次循环, 那么 一次循环里面 需要经历 从左到右,从上到下,从右到左,从下到上 四个小遍历
本题关键在于 矩阵四个角怎么分析,矩阵的四个角直接按顺序包含进去,从左到右结束,上边界减一,再从上到下
(从左到右 ,l到r是0到n-1, 从上到下 ,t到b是1到n-1;因为[1,n-1],在上一个小遍历的时候已经被填充了,)
坑:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> matrix(n,vector<int>(n));
int num=1 ; //需要填充进去的数值, 共填充n*n个数
int t=0,b=n-1,l=0,r=n-1;
//四个小遍历的i,j的初始值和终止是变化的,所以设定为变量
// 从横轴看,从左到右 ,l到r是0到n-1,
// 从纵轴看,从上到下 ,t到b是0到n-1;
while(num<=n*n){
//从左往右
for(int j=l;j<=r;j++){
matrix[t][j]=num++; //注意的分清不变量和变量
}
t++; // 上边界减少,
//从上到下
for(int i=t;i<=b;i++){
matrix[i][r]=num++;
}
r--;
//从右往左
for(int j=r;j>=l;j--){
matrix[b][j]=num++;
}
b--;
//从下到上
for(int i=b;i>=t;i--){
matrix[i][l]=num++;
}
l++;
}
return matrix;
}
};
补充:
vector声明二维数组
vector<vector<int>> table(size1, vector<int>(size2, 0)); // size1 是外围容器大小, size2是内部容器大小,0是赋的初值。 //即 容器(大小,内容)
for循环
for(单次表达式;条件表达式;循环体)每部分只能写一个表达式
数组总结
数组是存放在连续内存空间上的相同类型数据的集合
数组元素不能删除,只能覆盖,整体移动元素
数组和双指针真是相配,
学习了二分法,快慢双指针,滑动窗口,螺旋啊。
明确题目所给区间的开闭情况,循环的起始位置,终止位置及相应条件。
今日总结
螺旋矩阵题解看懂了,自己想出来很困难
力扣提交记录有备注啊!!!!页面小,之前没看见,好啊!!有备注!!太好了!!!