走投无路的算法学习笔记|Day002

目录

一、看视频/文章讲解

1.977.有序数组的平方

2.209.长度最小的子数组

3.59.螺旋矩阵II

二、无提示动手做题

1.977.有序数组的平方

2.209.长度最小的子数组

3.59.螺旋矩阵II


一、看视频/文章讲解

1.977.有序数组的平方

  感觉和相向双指针十分相似,而且允许额外复制一个数组后变得好理解多了。

2.209.长度最小的子数组

滑动窗口理解起来是真的很反常规,一般面对起始位置、终止位置都可变的情况,都会优先想用循环去控制起始位置(比如暴力法就是外层变量表示起始位置,内层变量表示终止位置),而滑动窗口是用循环去控制结束位置,再根据指定条件去控制起始位置

听到这里自己尝试去写了一下:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i=0;
        int minLen=nums.size();
        int findFlag=0;
        for(int j=0;j<nums.size();j++){
            int sum = 0;
            for(int k=i;k<=j;k++){
                sum += nums[k];
            }
            if(sum>=target){
                int tempLen = j-i+1;
                if(tempLen<=minLen){
                    minLen=tempLen;
                    findFlag=1;
                }
                i++;
                j--;//起始位置后挪时终止位置维持不变
            }
        }
        if(findFlag){
            return minLen;
        }else{
            return 0;
        }
        
    }
};

好家伙,根据报错调试修改了2次,总算能跑过大多数测试用例了,结果竟然超时了,肯定是坏在了sum的累加上,毕竟i不动的情况下没必要每次都从头累加,再一次好了:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i=0;
        int minLen=nums.size();
        int findFlag=0;
        int sum = 0;
        for(int j=0;j<nums.size();j++){
            sum += nums[j];
            if(sum>=target){
                int tempLen = j-i+1;
                if(tempLen<=minLen){
                    minLen=tempLen;
                    findFlag=1;
                }
                sum = sum-nums[i]-nums[j];
                i++;
                j--; //起始位置往后挪的时候终止位置暂时不动
            }
        }
        if(findFlag){
            return minLen;
        }else{
            return 0;
        }
        
    }
};

 竟然过了.....emmmmmm但是感觉自己写得...缝缝补补的

看完了视频可算是知道自己这缝缝补补的代码哪里怪了:

当起始位置需要连续后移时,我是用j--间接达到起始位置往后挪的时候终止位置暂时不动的目的的,这看起来远没有用while直观——起点需要向后移动到这个区间数值和小于目标值,然后才是终止位置的移动。

3.59.螺旋矩阵II

可以拿转的圈数作为结束循环的条件,用offset去表示每圈起始点的变化。

二、无提示动手做题

1.977.有序数组的平方

 大概是因为昨天在学习双指针的时候有看这题的题解,而且有了相向双指针的经验,这题自己写得时候还算顺利(虽然还是犯了个非常脑瘫的错误,在对结果数组赋值时把result打成了nums,LeetCode上直接报错溢出,本地调试了才发现,可能是之前都是在原数组上操作打习惯了),但是我的循环的结束条件感觉写得是指向新数组的指针走到底,总觉得Carl的以左右指针重合为结束条件好像更加科学

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> result(nums.size(),0);//todo 数组、指针、申明方式 此处为申明一个初始大小为nums.size()且初始值都为0的向量
        int i=0,j=nums.size()-1;//指向原数组的左右指针
        int k=j;//指向新数组的指针,因为原数组两端最大,所以从尾端开始赋值
        while(k>=0){
            if(nums[i]*nums[i]>nums[j]*nums[j]){
                result[k--]=nums[i]*nums[i++];
            }else{
                result[k--]=nums[j]*nums[j--];
            }
        }
        return result;
    }
};

2.209.长度最小的子数组

这题看视频时写了

3.59.螺旋矩阵II

在这一题里终于有一点点理解左闭右闭/左闭右开区间了:

一开始我想用while(val<n*n)作为出循环条件,因为这样需要定义的变量是最少的,但是按照左闭右开区间的写法,当n为奇数时,最后一圈是只有一个格子要填的,而左闭右开区间在离散的数上是根本取不到一个数的,因为当区间两端取值相等时,左闭右开区间就不合法了。

如果改成左闭右闭区间的写法,n为奇数时最后一格就能被正常填到了,但是因为矩形的每个端点都会被重复填写,val的值会对不上,所以还是只能写左闭右开区间,再对n为奇数的情况“打个补丁”

这题我目前能写出来的,变量尽可能简明的代码如下

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
        int round=1;
        int offset=0;
        int val = 1;
        while(round<=n/2){
            for(int i=0+offset,j=0+offset;j<n-1-offset;){
                //结束循环的条件是j<n-1-offset意味着最后一个元素不填,边界处理原则——左闭右开区间
                res[i][j]=val++;
                 j++;
            }
            for(int i=0+offset,j=n-1-offset;i<n-1-offset;){
                res[i][j]=val++;
                i++;
            }
            for(int i=n-1-offset,j=n-1-offset;j>0+offset;){
                res[i][j]=val++;
                j--;
            }
            for(int i=n-1-offset,j=0+offset;i>0+offset;){
                res[i][j]=val++;
                i--;
            }
            offset++;
            round++;

        }
        if(n%2==1){//如果是奇数行则对中间位置进行单独赋值
            res[n/2][n/2]=n*n;
        }
        return res;
    }
};

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值