代码随想录算法训练营第二天 | Leetcode 977 有序数组的平方 Leetcode 209 长度最小的子数组 Leetcode 59 螺旋矩阵Ⅱ

1.有序数组的平方

977. 有序数组的平方 - 力扣(LeetCode)

虽然暴力法好写但时间复杂度有点高,所以今天使用的方法叫双指针法,先分析这道题目,在数组两边的数据的平方一定是最大的,所以一个指针指向数组的头,一个指针指向数组的尾部,然后把它俩最大的放入结果数组的最后面,然后大的数据向小的数据的方向移动。

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[j]*nums[j];
            j--;
        }
        else{
            result[k--] = nums[i]*nums[i];
            i++;
        }
       }
       return result;
    }
   
};

2.长度最小的子数组

使用滑动窗户方法,

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。

那么滑动窗口如何用一个for循环来完成这个操作呢。

首先要思考 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置。

如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?

此时难免再次陷入 暴力解法的怪圈。

所以 只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置。

那么问题来了, 滑动窗口的起始位置如何移动呢?

其实是双指针的另一种指法。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
     int result = INT32_MAX;
     int sum =0;
     int subLength =0;
     int i =0;
     for(int j = 0; j<nums.size(); j++){
        sum+=nums[j];
        while(sum>= target){
            subLength = j-i +1;
            result = min(subLength,result);
            sum-=nums[i];
            i++;
        }
     }
     return result == INT32_MAX ? 0:result ;
    }
};

3.螺旋矩阵Ⅱ

这道题目可以说在面试中出现频率较高的题目,本题并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。

要如何画出这个螺旋排列的正方形矩阵呢?

相信很多同学刚开始做这种题目的时候,上来就是一波判断猛如虎。

结果运行的时候各种问题,然后开始各种修修补补,最后发现改了这里那里有问题,改了那里这里又跑不起来了。

大家还记得我们在这篇文章数组:每次遇到二分法,都是一看就会,一写就废 (opens new window)中讲解了二分法,提到如果要写出正确的二分法一定要坚持循环不变量原则

而求解本题依然是要坚持循环不变量原则。

模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。

可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此offer是路人

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n,vector<int>(n,0));
       int startx =0 ;
       int starty =0;
       int count =1;
       int loop = n/2;
       int mid = n/2;
       int i,j;
       int offset = 1;
       while(loop--){
        i = startx;
        j = starty;
        for(j; j<n-offset; j++){
            res[i][j] = count;
            count++;
        }
        for(i; i<n-offset; i++){
            res[i][j] = count;
            count++;
        }
        for(j;j>starty;j--){
            res[i][j] = count;
            count++;
        }
        for(i;i>startx;i--){
            res[i][j] = count;
            count++;
        }
        startx++;
        starty++;
        offset++;
       }
       if(n%2 == 1){
        res[mid][mid] = count;
       }
       return res;
    }
};

对于我来说这3题虽然简单但是我还是没有思路,说明我需要多刷题,加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值