LeetCode|数组|977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵||

 文章目录

一、977.有序数组的平方

1.几个注意点

  1. 当然可以用暴力算法,先把每个数都平方以下,然后再排个序。时间复杂度为O(n + nlogn)。
  2. 优化一下,使用双指针法。核心:虽然说原数组存在负数,负数平方后可能会比正数的平方大,但是数组平方的最大值只能在数组两端,不可能是中间部分。因此,可以定义一个新数组(长度等于原来数组),从这个新数组的末尾进行存放,每次存放进去最大值。

2.代码实现

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> result(nums.size(),0);//定义一个新数组,用来存放数字的平方
        int k = nums.size() - 1;
        for(int i = 0,j = nums.size() - 1;i <= j;){
            if(nums[i] * nums[i] > nums[j] * nums[j]){
                result[k--] = nums[i] * nums[i];
                i++; 
            }
            else{
                result[k--] = nums[j] * nums[j];
                j--;
            }
        }
        return result;
    }
};

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

1.几个注意点

  1. 可以用暴力算法实现,两个for循环,枚举出所有可能性,时间复杂度O(n^2)。
  2. 滑动窗口思想,用一个for循环即可。核心:for循环中的变量j用来控制窗口的末尾(即终止位置),当滑动窗口所圈住的子数组符合题目条件时,便开始缩短窗口起始位置。时间复杂度为O(n)。

2.代码实现(滑动窗口思想)

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result =  INT32_MAX;//result要设置成比原数组长度大,这样才能不断更新result
        int i = 0;
        int sum = 0;//记录目前滑动窗口中的各个元素之和
        int len;//记录子数组长度
        for(int j = 0;j < nums.size();j++){
            sum += nums[j];
            while(sum >= target){//只要sum大于target,就开始缩短窗口
                len = j - i + 1;//len为目前符合条件的子数组的长度
                result = len < result ? len : result;//更新result
                sum -= nums[i];
                i++;//缩短窗口(将窗口左端右移)
            }
        }
        return result < INT32_MAX ? result:0;
    }
};

3.代码实现(暴力算法)

看看就好,LeetCode中会超时。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = INT_MAX;
        int sum = 0;
        int len;
        for(int i = 0;i < nums.size();i++){
            sum = 0;//每次循环前,先将sum置零
            for(int j = i;j < nums.size();j++){
                sum += nums[j];
                if(sum >= target){
                    len = j - i + 1;
                    result = len < result ? len : result;
                    break;//一旦找到,就退出本轮循环,因为是求最小的子数组
                }
            }
        }
        return result < INT_MAX ? result : 0;
    }
};

三、59.螺旋矩阵||

1.思想

  1. 输入一个数n,形成一个n*n的矩阵(n*n的数组),从最外面一圈开始,一圈一圈的不断赋值。
  2. 那就需要知道一共有几圈:n/2。如果n是奇数,只需最后额外单独将最中心的那一个点赋值。
  3. 圈数知道了,现在就该讨论每一圈如何赋值:分成四条边,每一条边用一个for循环赋值,注意这里的四条边,每条边的起始位置都是不同的,所以这边定义两个变量startx,starty来标记四条边赋值的起始位置。
  4. 注意循环不变量,即每次对“边”赋值的时候,遵循同一个规定:我这里遵循每条边的第一个点至倒数第二个点赋值。这样每次对四条“边”赋值的时候,都是遵循着这种规定。
  5. 注意每一圈过后,要改变初始位置和偏移量offset。

2.代码实现

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> nums(n,vector<int>(n,0));//定义一个二维数组
        int startx = 0,starty =0;//startx记录初始行下标,starty记录初始列下标
        int loop = n / 2;//记录一共有几圈
        int offset = 1;//偏移量,每循环一圈之后,终止位置都要往左偏移一个
        int i,j;
        int count = 1;//记录对每条边每个点赋值的数据
        while(loop--){//每一圈对四条边赋值
            for(j = starty;j < n - offset;j++){
                nums[startx][j] = count++;
            }
            for(i = startx;i < n - offset;i++){
                nums[i][j] = count++;
            }
            for(;j > starty;j--){//此时j已经为正确的初始值,无需再赋值
                nums[i][j] = count++;
            }
            for(;i > startx;i--){//此时i已经为正确的初始值,无需再赋值
                nums[i][j] = count++;
            }
            //这一圈结束后,进行下一圈赋值时,需要改变初始位置
            startx++;
            starty++;
            offset++;//偏移量也需要+1
        }
        //如果输入的为奇数,那么还需对中心点赋一次值
        if(n % 2 == 1){
            int middle = n / 2;
            nums[middle][middle] = count;
        }
        return nums;
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值