算法训练day2|977.有序数组的平方|209.长度最小的子数组|59.螺旋矩阵II

一、977.有序数组的平方

  1. 自己的代码(也是暴力解)

这题比较简单,用sort排序后也会比较轻松,需要注意begin返回首元素位置,而end返回末尾元素位置的后一位,这里的位置指的是返回一个迭代器指向该位置。其次,cmp的写法也需要会,遇到降序排序可以用。同时要注意用到的函数属于哪个头文件,因为力扣所有头文件都会包含,所以不需要自己声明。

还有就是sort函数是左闭右开区间。

bool cmp(int a,int b){
    return a<b;
}
class Solution {
public:
     
    vector<int> sortedSquares(vector<int>& nums) {
        for(int i=0;i<nums.size();i++){
            //nums[i]=nums[i]*nums[i];
            nums[i]=pow(nums[i],2);
        }
        sort(nums.begin(),nums.end(),cmp);     
        //cout<<*nums.begin()<<" "<<*(nums.end()-1)<<endl;
        return nums;
    }
   
};
  1. 双指针优化(最优解)

因为是平方非递减,而原数组本就非递减,则两端的平方一定大于中间平方,于是双指针从两端往中间,平方大的值赋给新数组,则只需要一次遍历,时间复杂度O(n)

class Solution {
public:
     
    vector<int> sortedSquares(vector<int>& nums) {
        int size=nums.size();
        vector<int>result(size);
        int i=0,j=size-1;
        for(int k=size-1;k>=0;k--){
            if(nums[i]*nums[i]>=nums[j]*nums[j]){
                result[k]=nums[i]*nums[i++];
            }else{
                result[k]=nums[j]*nums[j--];
            }
        }
        return result;
    }
   
};

二、209.长度最小的子数组

  1. 暴力解在力扣上超时

暴力解两次循环即可,但是超时了,而且也很复杂

  1. 滑动窗口法

滑动窗口主要是右指针递增,左指针控制窗口减小以满足最小连续子数组。

需要注意的是时间复杂度,每个元素进入窗口1次,离开窗口一次,则是2n,因此时间复杂度为O(n)

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //滑动窗口法
        int result=nums.size()+1;
        int sum=0;
        int j=0;
        for(int i=0;i<nums.size();i++){
           sum+=nums[i];
           while(sum>=target){
               int sublength =0;
               sublength=i-j+1;
               result = result < sublength ? result : sublength;
               sum-=nums[j++];
           } 
        }
        return result == nums.size()+1 ? 0 : result;
    }
};

三、59.螺旋矩阵II

模拟类的题我总是做的很累,太难了0^0。

对于多层循环的变量总是找不太准。

打日志还是很重要的,调试的时候能找到出错的位置。

#include<cmath>
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>>result(n,vector<int>(n));//vector的二维数组
        int count=1;
        int out=1;
        int startx=0,starty=0;
        int offset=1;
        while(out++<=n/2){
            for(int i=startx;i<n-offset;i++){                
                result[startx][i]=count++;              
            }
            for(int i=starty;i<n-offset;i++){
                result[i][n-offset]=count++;
            }
            for(int i=n-offset;i>starty;i--){
                result[n-offset][i]=count++;
            }
            for(int i=n-offset;i>startx;i--){
                result[i][starty]=count++;
            }
            offset++;
            startx++;
            starty++;
        }
        if(n%2==1){
            result[n/2][n/2]=n*n;
        }
        return result;
    }
};

四、总结

今天学习了双指针、滑动窗口和强化了循环不变量。

双指针其实挺类似归并排序的,把需要的比较后放入新数组,滑动窗口主要是快指针用来遍历,慢指针用来控制大小,有点像昨天的移除元素的双指针。

对于今天的模拟题,看了代码后自己写一遍出来还是晕乎乎的,循环不变量能理解,对于内层循环的起始和终止并没有很好的把握住,对于这一类题目有点畏惧,还是要多刷题。

(5小时)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值