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

977. 有序数组的平方

暴力排序

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;
    }
};

这个时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度,但为了和下面双指针法算法时间复杂度有鲜明对比,记为 O(n + nlog n)。

双指针法

双指针思路:最大元素一定是在两边

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        // 双指针思想
        vector<int> result(nums.size(), 0);  // 创建整数向量(vector<int>),其大小与向量nums的大小相同,且所有元素都初始化为0
        int k = nums.size()-1;
        for(int i=0, j=nums.size()-1; i<=j; )  // 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;
    }
};

时间复杂度是 O(n)

209. 长度最小的子数组

滑动窗口

还是双指针的思想,但取双指针间的集合,更像是一个滑动窗口。

最重要的思路是如何移动起始位置

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //滑动窗口:双指针间的集合
        int result = nums.size();
        int i = 0, sum = 0;
        for(int j=0; j<nums.size(); j++){  // j是终止位置
            sum += nums[j];
            while(sum>=target){
                int subL = j-i+1;
                result = min(result, subL);
                sum -= nums[i];
                i++;
            }
        }
        if(i==0) return 0;  // 注意result没在循环里被赋值的情况
        else return result;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

为什么时间复杂度是O(n)

不要以为for里放一个while就以为是O(n^2), 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。

59. 螺旋矩阵Ⅱ

循环不变量

注意四条边节点的处理 -> 统一处理方式,左闭右开
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        // 创建一个大小为n x n的全0矩阵
        vector<vector<int>> nums(n, vector<int>(n, 0));
        int startx = 0, starty = 0;
        int i,j;
        int loop = n/2;  // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
        int offset = 1;
        int count = 1;  // 计数
        while(loop--){  
            j=starty;
            for(j = starty; j<n-offset; j++){
                nums[startx][j] = count++;
            }
            i=startx;
            for(i=startx; i<n-offset; i++){
                // 此时j=n-offset
                nums[i][j] = count++;
            }
            for( ; j>starty; j--){
                nums[i][j] = count++;
            }
            for( ; i>startx; i--){
                nums[i][j] = count++;
            }
            startx++;
            starty++;
            offset++;
        }
        if(n%2==1){
            // nums[i][j]=count;  // 注意n=1时这时i,j还没赋值
            int mid = n/2;
            nums[mid][mid] = count;
        }
        return nums;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值