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

977 总共花了1.5h,还是很不熟练,问题出在1自己思路太复杂 2 实现时出bug修bug

用双指针,一开始自己想的思路有点过于复杂,还分情况讨论 后来发现根本不用

不过两个双指针 时间复杂度都是O(n)

这个版本代码里出现过的问题有:vector后面要push back的话初始化就要设成0好点,后面要是想vec[i]赋值这样初始话要vector<int> res(size,value);这样比较好,找了半天错误其实问题就是 size初始化0和后面push back没统一

vector<int> sortedSquares(vector<int>& nums) {
        vector<int> res(0);
        
        //mixed
        int n_idx=nums.size()-1;
        int p_idx=nums.size();
        for (int i=0;i<nums.size();i++){
                if(nums[i]>=0){
                    n_idx=i-1;
                    p_idx=i;
                    break;
                }
            }
        cout<<n_idx<<endl<<p_idx<<endl;
        int res_idx=0;
        while(n_idx>=0 && p_idx<nums.size()){
            int n_square=nums[n_idx]*nums[n_idx];
            int p_square=nums[p_idx]*nums[p_idx];
            if(n_square<p_square){
                //res[res_idx++]=n_square;
                res.push_back(n_square);
                n_idx--;
            }
            else{
                res.push_back(p_square);
                p_idx++;
            }
        }
        //if either idx is invalid
        //all positive
        if(n_idx<0){
            for (int i=p_idx;i<nums.size();i++){
                
                res.push_back(nums[i]*nums[i]);
            }
            
        }
        //all negative
        else if(p_idx>=nums.size()){
            for (int i=n_idx;i>=0;i--){
                res.push_back(nums[i]*nums[i]);
            }
        
        }
        return res;

    }

看了代码随想录的思路,自己又简洁地写了一遍:

其实这个双指针根本不用分情况讨论,全正全负都照样这么写就行,从两头(绝对值最大)一个个比较

vector<int> sortedSquares(vector<int>& nums) {
        vector<int> res(nums.size(),0);
        int res_idx=nums.size()-1;
        int i=0; int j= nums.size()-1;
        while(i<=j){
            if(nums[i]*nums[i]>nums[j]*nums[j]){
                res[res_idx--]=nums[i]*nums[i];
                i++;
            }
            else{
                res[res_idx--]=nums[j]*nums[j];
                j--;
            }
        }

        return res;

    }

209 是medium 先暴力写了一遍,发现自己写暴力都没那么熟练,会出错:

sum忘记内循环重置0,最大值可以用INT32_MAX,这个O n*2,leetcode过不了

int minSubArrayLen(int target, vector<int>& nums) {
        int len=100000;
        int sum=0;
        int new_len=0;

        for(int i=0;i<nums.size();i++){
            sum=0;
            for(int j=i;j<nums.size();j++){
                sum+=nums[j];
                if(sum>=target){
                    len = std::min( j - i + 1, len);
                    break;
                }
            }
            
        }
       
        return (len==100000)?0:len;
    }

然后自己想了个双指针的方法

这是我一开始写的,双指针逻辑应该是对的,但是退出循环的逻辑和判断条件之类的有点问题,说明我的代码实现功底还是有问题,相当有问题

int minSubArrayLen(int target, vector<int>& nums) {
        int start=0; int end=0;
        int sum=0;
        int len=100000;
        while(start<nums.size() && end<=nums.size() && start<=end){
            
            if(sum<target){
                sum+=nums[end];
                cout<<"not enough: add "<< nums[end];
                end++;

                cout<<" (start, end)= "<<start<<" "<<end<<endl;
                cout<<"sum= "<<sum<<endl;
            }
            else{
                len=std::min(len,end-start);
                sum-=nums[start];
                cout<<"enough: deduct "<< nums[start];
                start++; 
                cout<<" (start, end)= "<<start<<" "<<end<<endl;
                cout<<"sum= "<<sum<<endl;

            }
        }
        return (len==100000)?0:len;
        
    }

chatgpt给我改成了这样:

int minSubArrayLen(int target, vector<int>& nums) {
    int start = 0, end = 0, sum = 0, len = INT_MAX;
    while (end < nums.size()) {
        sum += nums[end++];
        while (sum >= target) {
            len = std::min(len, end - start);
            sum -= nums[start++];
        }
    }
    return (len == INT_MAX) ? 0 : len;
}

补一句吐槽,挂着梯子用csdn是真的好卡

95 无算法,主要考察模拟过程+对代码的控制,说白了就是能否成功精准实现

不到10min出思路,剩下再花20min 自己实现+问gpt修改

自己实现的问题是,每一个方向进行完后,忘记做i 和 j的微调

 vector<vector<int>> generateMatrix(int n) {
        
        vector<vector<int>> vec(n, vector<int>(n, 0));
        int value=1;
        //4 while loop
        int i=0; int j=0;

        while(value<=n*n){

        //right
        while(j<n && vec[i][j]==0){
            vec[i][j]=value;
            value++;
            j++;
        }
        i++;
        j--;

        //down
        while(i<n && vec[i][j]==0){
            vec[i][j]=value;
            value++;
            i++;

        }
        i--;
        j--;

        //left
        while(j>=0 && vec[i][j]==0){
            vec[i][j]=value;
            value++;
            j--;
        }
        i--;
        j++;

        //up
        while(i>=0 && vec[i][j]==0){
            vec[i][j]=value;
            value++;
            i--;
        }
        i++;
        j++;

        }

        return vec;

    }
    

 这个是过了的,就是一开始我完全忘记写i-- , j++ 那些东西了

代码随想录的方法比我更robust,用了好几个值来精确定位,而不是用原来是不是0来判断

看了以后两个感想:

1.联想到二分法那里强调的,左开右闭 那种,一定要精确控制好,非常重要,就虽然我自己也能写出来题,但这种原则牢记在心 不容易出实现上的问题

2.这种题 精确实现真的非常重要,我能想出思路,但实现很有问题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值