【C++编程能力提升】

代码随想录训练营Day2 | Leetcode977、Leetcode209、Leetcode59

  • 一、977有序数组的平方
  • 二、209长度最小的子数组
  • 三、59螺旋矩阵II

一、977有序数组的平方

题目链接: 977、有序数组的平方

前提:数组元素有序,但存在正负数,因此平方后数组元素较大值总是在两端
核心:双指针法,left和right分别指向数组首尾;新数组插入元素需要从后往前,原因是比较left和right指向元素时总是从绝对值较大值开始,即先确定较大值,自然需要插入到新数组的末尾,然后依次往前插入。
方法:第一次比较left和right指向元素时,将绝对值较大的平方插入到新数组的末尾,插入一个元素后需要将指向新数组的指针前移,同时将该绝对值较大的left或right后移或前移,即向中间靠近;当left>right时表示原数组所有元素均已比较,结束循环。

    vector<int> sortedSquares(vector<int>& nums) {
    //双指针:left&right较大数移至新数组末尾
    vector<int> res(nums.size(),0);
    int left=0;
    int right=nums.size()-1;
    int idx=right;//指向新数组的末尾
    while(left<=right)
    {//左闭右闭
        if(abs(nums[left])<=abs(nums[right]))
        {//right指向元素需添加到res数组
            res[idx--]=nums[right]*nums[right];
            right--;
            //idx--;
        }
        else
        {//left指向元素需添加到res数组
            res[idx--]=nums[left]*nums[left];
            //idx--;
            left++;
        }
    }
    return res;
    }

二、209长度最小的子数组

题目链接:209、长度最小的子数组

前提:子数组是连续的;且要求长度最小。
核心:滑动窗口,实质是快慢指针,fast指针遍历数组元素直至满足构成连续子数组的条件,slow指针控制该满足条件的连续子数组是长度最小的,简答而言,fast指针控制连续子数组的右边界,slow指针控制长度最小的连续子数组的左边界。
方法:当fast遍历到某一元素使得此时的连续子数组满足条件时,需要记录此时的子数组长度,并与此前的最小长度比较,保留最小长度,然后更新此时的连续子数组,slow前移,再次判断更新后的连续子数组是否满足条件,直至不满足条件时退出循环,退出时已记录了满足条件的子数组的最小长度。
注意:连续子数组的最小长度不能初始化为数组大小,因为数组大小的最小长度也是可能存在的,只能初始化为INT_MAX,因为该值是不可能存在的,即如果该数组无法找到满足条件的连续子数组,那么最小长度依然为初始化的INT_MAX,返回时可根据是否为INT_MAX确定是否需要返回0.

    int minSubArrayLen(int target, vector<int>& nums) {
    //滑动窗口,实质是快慢指针,fast遍历nums控制最小子数组的右边,slow控制最小子数组的左边
    int slow=0;
    int sum=0;
    int minLen=INT_MAX; //ps. 最小子数组长度初始化不能为nums.size(),必须为最大值
    for(int fast=0;fast<nums.size();fast++)
    {//遍历nums求解sum,直到sum>=target控制slow指针
        sum+=nums[fast];
        while(sum>=target)
        {
            int len=fast-slow+1;    //当前连续子数组的长度
            minLen=minLen>len?len:minLen;//与初始化或前一个最小长度比较,目的是保留最小长度
            sum-=nums[slow];
            slow++;
        }
    }
    return minLen==INT_MAX?0:minLen;
    }

三、59螺旋矩阵II

题目链接:59、螺旋矩阵II

核心:循环不变量规则,即构造矩阵(遍历上行右列下行左列)时必须满足左闭右开或左开右闭,也就是说,比如构造矩阵的第一行元素时(上行),只给除第一行最后一个元素之外的所有元素赋值;接着给第一列元素赋值时(右列),同样除了右列的最后一个元素的其他元素进行赋值;保证不再重复。
注意1:构造矩阵时,循环遍历的个数与n有关,即需要循环n/2次;
注意2:第一次循环时从start=0开始,第二次循环时由于外层已被赋值,故需从start++开始;为方便赋值,分别设置横坐标和纵坐标i=startx, j=starty;
注意3:左闭右开或左开右闭由offset控制,将offset初始化为1,即第一次循环时需要赋值n-offset个元素;此后的循环由于外层已被赋值,也需要对offset++;
注意4:矩阵最中间的元素无法通过循环被遍历到,因此需要单独赋值。

    vector<vector<int>> generateMatrix(int n) {
    //模拟矩阵过程需要坚持循环不变量规则,即上行右列下行左列循环过程中保证左闭右开或左开右闭
    vector<vector<int>> mat(n,vector<int> (n,0)); //初始化返回的二维数组n*n
    int mid=n/2;
    int loop=n/2;
    int num=1;
    int startx=0;
    int starty=0;
    int offset=1;//左闭右开,第一个loop保留一个元素不填充
    while(loop--)
    {
        int i=startx;
        int j=starty;

        for(;i<n-offset;++i)
            mat[j][i]=num++;
        for(;j<n-offset;++j)
            mat[j][i]=num++;
        for(;i>startx;--i)
            mat[j][i]=num++;
        for(;j>starty;--j)
            mat[j][i]=num++;
        
        startx++;
        starty++;
        offset++;
    }
    if(n%2)
        mat[mid][mid]=num;
    return mat;
    }

你可能感兴趣的:(C++编程,c++,leetcode)