Day2|Leetcode977. 有序数组的平方 Leetcode209. 长度最小的子数组 Leetcode59. 螺旋矩阵 II

习惯于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 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值