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

今天是6.9,正值端午假期,没啥事把前天的博客补一下哈哈哈,补进度的感觉可太难受了。。。

每道题的方法:

977:利用双指针法,两个指针分别从数组的两遍(两边是较大的值)遍历去填充新容器。

209:利用双指针法,从同一个地方开始移动,但是先移动终止指针,再通过while循环移动起始指针,不断改变窗口的位置和大小。

59:因为是填充二维数组所以也相当于利用双指针法,不过每次循环注意遵循循环不变量的原则,同时还需要注意通过改变一些值来控制边界。

题目一链接:977. 有序数组的平方 - 力扣(LeetCode)

思路:构造一个与nums大小一样的容器result,然后利用i,j两个指针遍历两边取最大值(nums数组的特性:平方后较大值在两侧)再利用slow指针反向填充(因为要求递增的顺序)result容器。

代码:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        //先将数组每个数都平方
        for(int i = 0;i < nums.size();i ++) {
            nums[i] *= nums[i];
        }
        //定义一个新的result容器
        int n = nums.size();
        vector <int> result(n,0);
        //slow用来填充新的result容器
        int slow = n - 1;//从最后开始填充
        //定义i,j两个指针
        for(int i = 0,j = n - 1;i <= j;) {//nums两侧的数平方后有最大值
            if(nums[j] >= nums[i]) {
                result[slow --] = nums[j];
                j --; 
            }
            else {
                result[slow --] = nums[i];
                i ++;
            }
        }

        return result;
    }
};

难点:

解释细节4:通过观察可得,所以要求两个指针从两侧开始向中间靠拢来便利nums。

解释错误点2:slow应该从nums.size() - 1,开始




题目二链接:59. 螺旋矩阵 II - 力扣(LeetCode)

思路:遵循左闭右开的原则进行很多圈的遍历和赋值。

代码:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n,vector<int>(n,0));
        int startx = 0,starty = 0;//定义每一圈的起始位置,
        int loop = n / 2;//控制遍历的圈数
        int mid = n / 2;//如果n为奇数的话,最后得考虑最中间的那个点
        int count = 1;//用来给每一位赋值
        int offset = 1; 需要控制每一条边遍历的长度,每次循环右边界收缩一位:第一圈是减一,后面逐渐递增
        int i,j;//用来便利整个矩阵

        while(loop --) {
            //改变每一圈开始遍历的位置
            i = startx;
            j = starty;
            //第一圈遍历:    
            for(j;j < n - offset;j ++) {
                res[i][j] = count ++;
            }

            for(i;i < n - offset;i ++) {
                res[i][j] = count ++;
            }

            for(j;j > starty;j --) {//遵循左闭右开的原则
                res[i][j] = count ++;
            }

            for(i;i > startx;i --) {
                res[i][j] = count ++;
            }
            //控制每一条边遍历的长度
            offset ++;
            //改变每一圈开始遍历的位置
            startx ++;
            starty ++;
        }

        if(n % 2 != 0) res[mid][mid] = count;
        return res;
    }
};

难点:

解释细节1:因为遵循循环不变量:区间左闭右开。

解释细节5:奇数时只需要在正中间加一个数

额外细节:二维数组的定义: res(n,vector<int>(n,0))



题目三链接:209. 长度最小的子数组 - 力扣(LeetCode)

思路:通过两个cur指针(有一个需要提前移动)遍历两个链表来寻找两个单链表的第一个相同节点(指的是LinkedNode,而不是节点的值),然后输出节点即可。

代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //定义最大值
        int result = INT32_MAX; 
        int sum = 0;

        for(int j = 0,i = 0;j < nums.size();j ++) {//j 代表终止位置
            //起始位置移动的逻辑:
            sum += nums[j];
            while(sum >= target) {//写完if后发现后面需要不断循环这个过程,所以这里是while而不是if
                int subl = j - i + 1;
                res = min(res,subl);
                sum -= nums[i ++];
            }
        }
    
        if(res == INT32_MAX) return 0;
        else return res;
    }
};

难点:

解释细节2:当通过移动终止位置而求出的sum大于target时再移动起始位置。

解释细节3:写完if后发现后面需要不断循环这个过程,所以这里是while而不是if

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值