习惯于acm模式的我,leetcode的模式好怪,OK,废话少说,我们直接进入正题:
Leetcode 977 有序数组的平方
题目链接997 有序数组的平方
这个题第一眼看的时候就是暴力法:先把数组中的每个元素平方,然后直接一个快排就解决了
直接上代码(leetcode模式)
要注意一点是在leetcode中的sort排序怎么写:
sort(nums.begin(),nums.end());
下面是完整暴力代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i=0;i<=nums.size()-1;i++){
nums[i]*=nums[i];
}
sort(nums.begin(),nums.end());
return nums;
}
};
另一种方法,前面我们刚刚学习了双指针法:
本题目就体现了双指针法
解释一下为什么可以用双指针:对于nums来说,平方之后的元素一定是两边的最大,从外向里依次是从大到小,所以就可以用双指针来比较平方后元素的大小,大的放新数组的最后,然后通过指针的移动,不停的靠近最中间,当两指针重合时,就完成了新数组元素的传递
用一个图来解释一下更好理解:
注意一下定义新数组的方式(leetcode)
vector<int> result(nums.size(),0);
下面是代码:
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;//此时result是从小到大排序的
}
};
Leetcode 209 长度最小的子数组
题目链接209 长度最小的子数组
同样是两种方法
第一种暴力法,把全部的符合的集合区间全部求出来,然后来一个判断解决全部问题
直接上代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int ans;//集合数值
int lengt = 0;//集合长度
int a = INT32_MAX;
//双循环,全部遍历一遍
for(int i=0;i<nums.size();i++){
ans = 0;
for(int j=i;j<nums.size();j++){
ans+=nums[j];
if(ans>=target){//有大于目标数时,就记录下长度
lengt = j-i+1;//记录长度
a = a < lengt ? a : lengt;//更新最小值
break;//停止,退到下一步循环中
}
}
}
return a == INT32_MAX ? 0 : a;//特判
}
};
第二种 滑动区间法(一个for循环解决两个嵌套的问题) 有点运用双指针的思想了,首先将j指针放到滑动区间终止端(j指针属于区间的终止端),然后j指针不停的扩大范围,直到扩大到符合要求,就停下判断,再通过i指针(i指针属于区间的起始端)来不断缩小区间范围求出最小值,这就是大概的思路
下面上代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int ans = 0;//区间集合数值
int result = INT32_MAX;//我们所求的最小值
int i=0;//
int len=0;//区间长度
for(int j=0;j<=nums.size()-1;j++){//终端指针不断后移
ans+=nums[j];//区间总和值不断增大
while(ans>=target){//判断是否符合要求
len = j-i+1;//更新区间长度
result = min(result,len);//更新result
ans-=nums[i];//这是滑动区间的核心,起始指针i后移,开始缩小区间长度,不断更新区间最小长度,直到找打最小的区间长度停止更新。
i++;
}
}
if(result==INT32_MAX){//特判
return 0;
}else{
return result;
}
}
};
核心代码(比较重要):
while(ans>=target){
len = j-i+1;
result = min(result,len);
ans-=nums[i];
i++;
}
Leetcode 59 螺旋矩阵
题目链接 59 螺旋矩阵
本题目的主要思路就是一个运用二维数组,而在讨论边界情况时一定要注意循环不变量问题,边界讨论时一定要有规律
下面直接就上代码:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int startx = 0;//每个循环圈的起始位置
int starty = 0;
int loop = n/2;//循环几圈,如果奇数圈最后会剩下最后一个元素,后面会有讨论
int offset = 1;//控制遍历长度,讨论右边界时要舍弃边缘下标值
int cnt = 1;//要赋值的数
int mid = n/2;//矩阵中间的位置
int i,j;
vector<vector<int>>nums(n,vector<int>(n,0));//二维数组的定义
while(loop--){//螺旋几圈
i = startx;//i和j都是处于起始位置
j = starty;
for( j = starty;j<n - offset;j++){// 模拟填充上行从左到右
nums[startx][j] = cnt++;
}
//要注意,i,j没有被int重新定义,所以i,j会继承for循环的值
for( i = startx;i<n- offset;i++){// 模拟填充右列从上到下
nums[i][j] = cnt++;
}
for( ; j>starty ; j--){ // 模拟填充下行从右到左
nums[i][j] = cnt++;
}
for( ; i>startx;i--){// 模拟填充左列从下到上
nums[i][j] = cnt++;
}
startx++;//起始位置改变+1,螺旋圈变小
starty++;//
offset+=1;//边缘下标值需要-1,对于offset就是+1
}
if(n%2){//奇数情况
nums[mid][mid] = n*n;//最后一个数放在最中间
}
return nums;//完成
}
};
赶到11点了,睡觉了 ,end end end