数据结构以学带练day2——数组平方排序、螺旋矩阵、滑动窗口法

404 阅读3分钟

题目

977.有序数组

image.png

自己第一想法(20分钟内未做出)

1、先for进行平方,再for进行判断前后大小,前大后小就交换(会有逻辑问题:比如第3个小于第1个这种情况)。

2、先for进行平方,再用sort()函数,在std命名空间内,无法使用。且该方法时间复杂度为O(nlogn)O(nlogn)

代码随想录方法

双指针法

  1. 关键点:非递减顺序数组,平方后一定呈现两头大,中间小

  2. 以空间换时间:定义新数组(要指定大小和数组内容),用于存放最终的结果。

  3. 双指针:分别指向原数组的一头一尾,进行对比,然后取更大的数

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        //定义容器大小为nums.size(),内容用0填补
        vector<int> result(nums.size(), 0);
        int k = nums.size()-1;
        //head指向原数组头,tail指向原数组尾,判断结束条件为它俩重合
        for(int head = 0,tail = nums.size()-1;head<=tail;){
            //如果head的平方的值大于tail的平方的值
            if((nums[head]*nums[head]) > (nums[tail] * nums[tail])){
                result[k] = (nums[head]*nums[head]);
                k--;
                head++;
            }
            //如果head的平方的值小于等于tail的平方的值
            else{
                result[k] = (nums[tail]*nums[tail]);
                k--;
                tail--;
            }
        }
        return result;
    }
};

暴力方法:sort()排序

class Solution {
public:
    vector<int> sortedSquares(vector<int>& A) {
        for (int i = 0; i < A.size(); i++) {
            A[i] *= A[i];
        }
        sort(A.begin(), A.end()); // 快速排序
        return A;
    }
};

209. 长度最小的子数组

image.png

自己想法(15分钟内未做出)

采用双指针方法,快指针进行遍历求和,当sum值大于等于target时,记录快指针下标,则更新现在最小数组长度为快指针的下标+1,且更新慢指针+1,并把慢指针的下标赋值给快指针,再次进行上述运算,直到慢指针指向数组最后则停止。但编译报错,不知道问题出在哪里。

代码随想录方法

运用双指针方法:

  • 快慢指针皆指向开头,快指针一直向后滑动,直到找到大于等于target的sum值,判断此时最小数组长度(fast-slow+1),并进行result更新。

  • 之后慢指针向后移动1次,相应的sum应当减去开头的值,再次判断sum>=target,满足则慢指针移动,不满足则快指针继续移动,直到快指针指向最后。

  • 如果最后的结果result依旧是等于初始定义的result == INT32_MAX,则表示找不到,返回0。

  • 关键点:判断sum>=target要用while循环判断,而不是用if判断。因为当slow向后滑动一次且sum-=num[slow]后,此时得到的sum有可能仍大于等于target,此时相较上一次的result长度就减了1

209.长度最小的子数组.gif

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int slow = 0;
        int fast = 0;
        int sum = 0;
        int result = INT32_MAX;
        //快指针一直向后滑动
        while(fast < nums.size()){
            //sum累加
            sum += nums[fast];
            //满足大于等于target的sum值
            while(sum>=target){
                //此时数组长度
                int subL = (fast - slow + 1);
                //result更新
                result = min(result,subL);
                //慢指针向后移动1次,相应的sum应当减去开头的值
                sum -= nums[slow];
                slow++;
            }
            fast++;
        }
        if (result == INT32_MAX) return 0;
        return result; 
    }
};

59.螺旋矩阵 II

image.png

代码随想录方法

按照统一左闭右开的规则进行依次填充:

  • 1、根据n判断一共会循环几圈:loop = n/2;
  • 2、二维容器的定义方法:vector<vector<int>> res(n,vector<int>(n,0));
  • 3、n为奇数时,对中间位置进行单独处理
  • 4、每层填充的数的数量有一定规律,利用offset进行控制
  • 5、count用于记录要填的数的数值大小
  • 6、startx和starty用于记录每圈的起始填充位置,每向内一圈,startx和starty都+1
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        //定义一个二维数组(容器)
        vector<vector<int>> res(n,vector<int>(n,0));
        //一共转多少圈
        int loop = n/2;
        //若n为奇数的 中间位置。例如n=3,中间位置为(1,1)
        int mid = n/2;
        //起始位置
        int startx = 0;
        int starty = 0;
        //圈层控制变量
        int offset = 1;
        //要填入的数值
        int count = 1;
        //初始化i和j
        int i;
        int j;
        while(loop--){
            i = startx;
            j = starty;
            //遵循左闭右开进行遍历
            //上,j最终加到n-offset-1,并保持
            for(j = starty;j<n-offset;j++){
                res[i][j] = count++;
            }
            //右,i最终加到n-offset-1,并保持
            for(i = startx;i<n-offset;i++){
                res[i][j] = count++;
            }
            //下,j减到starty+1
            for(;j>starty;j--){
                res[i][j] = count++;
            }
            //左,i减到startx+1
            for(;i>startx;i--){
                res[i][j] = count++;
            }

            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
            startx++;
            starty++;
            // offset 控制每一圈里每一条边遍历的长度
            offset++;
        }
        //上面循环结束若n为奇数,中间的框会没被赋值
        if(n%2!=0){
            res[mid][mid] = count++;
        }
        return res;
    }
};

今日收获,记录一下自己的学习时长

今日三道题都有一些卡壳,特别最后的数组螺旋,完全无从下手。就算看完一遍视频自己写也出现一些问题。需要加以巩固。

学习时长:3h+30min。