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

98 阅读1分钟

977.有序数组的平方

题目链接:leetcode.cn/problems/sq…

要点

  • 给定一个非递减的数组,两头是平方大的数字,设置头尾两个相向的指针,选大的元素从后往前放在result数组中

双指针法

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> tmp(nums.size());
        int left = 0;
        int right = nums.size()-1;
        for (int i = nums.size()-1; i>=0; i--){
            if (nums[left]*nums[left] < nums[right]*nums[right]){
                tmp[i] = nums[right] * nums[right];
                right--;
            }else{
                tmp[i] = nums[left] * nums[left];
                left++;
            }
        }
        return tmp;
    }
};

总结

在for循环内部,每轮都会有++--的操作,在nums.size()轮内会安排完所有的元素,不用循环判断条件left<=right

209.长度最小的子数组

题目链接:leetcode.cn/problems/mi…

滑动窗口法

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum = 0;
        int slow = 0;
        int minlen = nums.size()+1;
        for (int fast = 0; fast < nums.size(); fast++){//移动前面指针
            sum += nums[fast];
            while (sum >= target){//缩slow指针,是while,不是if
                minlen = minlen < (fast-slow+1) ? minlen : (fast-slow+1);//满足条件的子数组记录
                sum -= nums[slow];
                slow++;
            }
        }
        return minlen == (nums.size()+1) ? 0 : minlen;
    }
};

要点

  • minlen初始值需要一个大于数组长度的值
      1. 更新minlen是选择较小的子数组长度,故初始值需要很大
      1. 因为数组长度也可能是解,而无子数组应返回0,故初始值不能设为nums.size()
  • 简单的if判断,如a = min(a, b)更新操作,可以用三目运算符? :代替
  • 滑动窗口实现时,前后两个指针都是往一个方向,不回头的移动

总结

两个指针移动,fast指针先移动,slow根据条件再移动,fast指针的移动写在for循环里,slow指针满足while条件再移动。fast移动只有大于等于target才停止,slow移动只有sum < target了才停止。

59.螺旋矩阵II

题目链接:leetcode.cn/problems/sp…

模拟螺旋的过程

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int startx = 0; int starty = 0;
        int offset = 1;
        int loop = n/2;
        int i, j;
        int count = 1;

        while (loop--){  //每轮完成一圈的赋值
            i = startx;
            j = starty;

            for (j = starty; j < n-offset; j++){   //依次顺时针行列赋值
                res[startx][j] = count++;
            }

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

            for (; j > starty; j--){
                res[i][j] = count++;
            }

            for (; i > startx; i--){
                res[i][j] = count++;
            }

            startx++; starty++; offset++;
        }

        if (n%2 == 1){
            res[n/2][n/2] = count;
        }

        return res;
    }
};

要点

  • 每轮中的i,j为模拟螺旋的变量,startx, starty, offset为每轮变化,但轮内不变化的参数
  • 每轮需要注意:起始的坐标、for循环的左闭右开边界、i,j 的移动轨迹
  • i, j 为有实际意义的变量,不要初始化在for循环内作临时变量

总结

螺旋矩阵作为模拟题,想清楚每轮的赋值顺序和边界控制,代码还是挺清晰的。

数组章 总结

  • 二分法
  • 双指针
  • 滑动窗口
  • 模拟

重点是双指针的用法,双指针可以有删除元素中的同向的快慢指针,也有元素平方的相向的双指针,使用须灵活。 滑动窗口也是一种特殊的同向双指针。