day2-977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

第一题-977.有序数组的平方

题目-有序数组的平方

自己尝试

看到这道题,我的第一个想法便是直接遍历原数组平方,再给新数组排序(冒泡排序)

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int len = nums.size();//原数组大小
        for (int i = 0; i < len; i++) {
            nums[i] = nums[i] * nums[i];//得到平方后的新数组
        }
        //冒泡排序得到新数组
        for (int j = len-1; j >=0;j--) {
            for (int i = 0; i < j; i++) {
                //如果前一个数大于后一个数,交换位置
                if (nums[i] > nums[i + 1]) {
                    int change;
                    change = nums[i];
                    nums[i] = nums[i + 1];
                    nums[i + 1] = change;
                }
            }
        }
        return nums;
    }
};

成功解决问题,但执行时间比较长

这里整理一下内部排序的时间复杂度:

  • O(nlogn): 快速排序、堆排序和归并排序
  • O(n^2): 直接插入排序、冒泡泡排序和简单选择排序
  • O(n): 基数排序

根据视频解答-双指针法

使用双指针法,由于原始的数组是非递减的,因此只需要比较负数的平方和正数的平方大小,更改顺序即可,即数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。可以考虑双指针法了,i指向起始位置,j指向终止位置。

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> new_nums(nums.size(),0);
        int k = nums.size() - 1;//用于从后往前存新数组
        int i, j;//双指针 i-从前往后,j-从后往前
        //循环条件需要i=j,否则缺失nums[i]=nums[j]的这个元素
        for (i = 0, j = nums.size()-1; i <= j;){
            //左边的平方比右边的平方大
            if (nums[i] * nums[i] > nums[j] * nums[j]) {
                new_nums[k] = nums[i] * nums[i];
                i++;
                k--;
            }
            //右边的平方比左边的平方大或相等
            else {
                new_nums[k] = nums[j] * nums[j];
                j--;
                k--;
            }
        }
        return new_nums;
    }
};

出现的问题:

原因:没有初始化新数组new_nums,增加语句vector<int> new_nums(nums.size(),0);

第二题-209.长度最小的子数组

题目

自己尝试

我的想法是先对数组由大到小排序,再从前往后相加数组的每一个值,并设置一个计数器,s直到总和大于或等于target,输出计数器的值,如果整个数组的和都小于target则输出0

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //降序排序
        sort(nums.rbegin(), nums.rend());
        int total = 0;
        for (int i = 0; i < nums.size(); i++) {
            total = total + nums[i];
            if (total >= target) {
                return i + 1;
            }
        }
        return 0;
    }
};

问题:没有考虑到题目中要求“长度最小的 连续子数组 ”,这样求出来的未必连续,因此有些测试用例没有通过

根据视频解答-滑动窗口

【滑块移动】遍历终止位置,找到第一个满足条件的数组元素个数,进入循环,如果一直满足条件则起始位置往后移动,如果不满足条件则终止位置往后移动,找到最少的个数

  • 注意,此处result起始取一个较大的值,便于后续比较寻找最小的值
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i = 0, total=0,result=1000000;//起始位置
        //j是终止位置
        for (int j = i; j < nums.size(); j++) {
            //从起始位置加
            total = total + nums[j];
            while(total >= target) {
                if (j - i + 1 < result) {
                    result = j - i + 1;
                }
                //此时符合条件,移动起始位置
                total = total - nums[i];
                i++;
            }
        }
        if (result == 1000000)return 0;
        return result;
    }
};

第三题-59.螺旋矩阵II

根据视频解答

重点:左闭右开,其实内容不难,就是比较麻烦,好早最后都解决了!画了一个简略图如下,可以方便理解

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> num(n, vector<int>(n));
        int count = 1;
        int startx=0, starty=0;
        int len = n;
        if (n == 1) {
            return { {1} };
        }
        //绕n/2圈
        for (int quan = 0; quan <len / 2; quan++) {
            //第一行除了最后一个元素
            for (int i = starty; i < n - 1; i++) {
                num[startx][i] = count;
                count++;
            }
            //最右一列除了最后一个元素
            for (int i = startx; i < n - 1;i++) {
                num[i][n - 1] = count;
                count++;
            }
            //最后一行除了最后一个元素
            for (int i = n - 1; i > starty; i--) {
                num[n - 1][i] = count;
                count++;
            }
            //第一列除了最后一个元素
            for (int i = n - 1; i >startx; i--) {
                num[i][starty] = count;
                count++;
            }
            startx++;
            starty++;
            n = n - 1;
        }
        //n为奇数
        if (len % 2 != 0) {
            num[len / 2][len / 2] = count;
        }
        return num;
    }
};

总结

代码随想录 (programmercarl.com)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值