算法训练Day02|数组part02(LeetCode977.有序数组的平方、LeetCode209.长度最小的子数组、LeetCode59.螺旋矩阵II)

文章讲解
视频讲解

977.有序数组的平方

题目链接

重点

重点掌握双指针法,数组平方的最大值就在数组的两端,所以在数组两端分别加一个指针,平方后比较大小,时间复杂度是 O(n )。

代码

  • 暴力解法
    直接对所有元素平方,使用sort排序,时间复杂度是 O(n + nlogn)。
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;

    }
};
  • 双指针法
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        //第一次错在没有对vector进行赋值或构造
        vector<int> result;//也可以直接vector<int> result(nums.size(),0);
        result.assign(nums.size(),0);
        int k=nums.size()-1;
        int i=0,j=nums.size()-1;
        while(i<=j){
            if(nums[i]*nums[i]<=nums[j]*nums[j]){
                result[k--]=nums[j]*nums[j];
                j--;
            }
            else{
                result[k--]=nums[i]*nums[i];
                i++;
            }
        }
        return result;  
    }
};

209.长度最小的子数组|滑动窗口

题目链接

重点

暴力解两个for循环, 对每一个起始位置都往后遍历一遍,一直到有满足条件的子序列,时间复杂度是O(n^2)。
重点是滑动窗口(也是双指针),for循环里表示的是终止位置,向后遍历,满足条件后不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)(每个元素进来操作一次,出去操作一次,2n)。
在这里插入图片描述

ps:这个地方我真的想了好久,主要在于有一些子序列根本不会出现,难道不会错过吗?其实不会的,如果那个子序列都能满足条件 ,终止位置一定会在这个子序列的末尾停下的。

代码

  • 暴力解法
//程序是对的,但在leetcode是超时的
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int len=INT32_MAX;//int类型最大的数
        for(int i=0;i<=nums.size()-1;i++){
            int sum=0;
            for(int j=i;j<=nums.size()-1;j++){
                sum+=nums[j];
                if(sum>=target){
                    len=min(len,j-i+1);
                    break;//终止当前循环
                }
            }
        }
        return len==INT32_MAX?0:len;
    }
};
  • 滑动窗口
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum=0;
        int len=INT32_MAX;//只能大写
        int i=0;
        for(int j=0;j<=nums.size()-1;j++){
            sum+=nums[j];
            while(sum>=target){//这里不能写if,起始位置要持续向前移动
                len=min(len,j-i+1);
                sum-=nums[i];
                i++;
            }
        }
        return len==INT32_MAX?0:len;
    }
};

59.螺旋矩阵II

题目链接

重点

螺旋矩阵其实不涉及什么算法,唯独就是容易绕,边界条件要遵循循环不变量。如果矩阵的边长是n,则需要绕n/2圈,一圈四条边,每一条边都要左闭右开。模拟遍历二维矩阵时间复杂度 O(n^2)。

代码

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        //注意这个vector二维数组的构造方法
        vector<vector<int>> result(n,vector<int>(n,0));
        int count=1;     
        int startx=0,starty=0;
        int x=startx,y=starty;
        int offset=1;
        int loop=n/2;
        while(loop--){ 
            for(y=starty;y<n-offset;y++){
                result[startx][y]=count++;
            }
            for(x=startx;x<n-offset;x++){
                result[x][y]=count++;
            }
            for(;y>starty;y--){
                result[x][y]=count++;
            }
            for(;x>startx;x--){
                result[x][y]=count++;
            }
            //第一次循环结束后,这里x已经--了,等于0了
            offset++;
            startx++;
            starty++;       
        }
        if(n%2){
            int middle=n/2;
            //这里索引不能用表达式,要重新定义一个变量
            result[middle][middle]=count++;
        }
        return result;
    }
};

总结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值