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

1,123 阅读2分钟

day2

今天早上刷了一遍昨天的两道题,印象更深刻了点。拓展就等以后二刷再试试。

好的,那么回到今天的题:

977.有序数组的平方

题目链接:leetcode.cn/problems/sq…(因为再把题目描述放上来会很占篇幅,今天开始就只放链接)

这题我一开始就按照提议先将整个数组元素平方后再排序,虽然ac了但是肯定不满足。因为这段时间学的是数组,昨天重点是指针,我就从指针的方向去思考。大体的思路是:先给整个数组元素取平方,设置两个指针,分别放在数组首尾,依次对比,将较大的元素放在新数组的尾部,旧数组中较大元素对应的指针往另一个指针方向移动,直到两指针重合结束。我看了一下官方答案,确实有这个思路,一下子十分开心。以下是我的代码:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int i = 0;
        int n = nums.size();
        int j = n - 1;
        vector<int> ans(n, 0);
        int pos = n - 1;
        while (i <= j) {
            if (nums[i] * nums[i] > nums[j] * nums[j]) {
                ans[pos] = nums[i] * nums[i];
                i++;
            }   else {
                ans[pos] = nums[j] * nums[j];
                j--;
            }
            pos--;
        }
        return ans;

        

    }
};

答案中还有第二种,我觉得那种就有点麻烦了,而且还得考虑单个指针移动至边界的情况。

209.长度最小的子数组

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

这题解决的思路其实还是双指针,和上一题的区别就是这个是可以抽象为一个滑动的窗口,根据当前子序列的大小动态调节子序列的起始位置,从而省去了暴力解法里面重复的操作。

代码如下:

public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = 1000001;
        int i = 0; //滑动窗口起始位置
        int sum = 0;//滑动窗口数值之和
        int subL = 0;//滑动窗口长度
        for (int j = 0; j < nums.size(); j++) {
            sum += nums[j];
            while (sum >= target) {
                subL = j - i + 1;
                result = result < subL ? result : subL;
                sum -= nums[i++];
            } 
        }
        return result == 1000001 ? 0 : result;


    }
};
螺旋矩阵II

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

这题重点不在算法,主要是构建螺旋画图的思路比较难。 一开始我看了好几分钟硬是没看懂要怎么实现,暴力解法可以是放弃了。然后看了卡哥的题解,感觉重点是处理规则要统一,这个和之前的二分很像。 代码如下:

public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
        int startx = 0, starty = 0; // 每一个圈的起始位置
        int loop = n / 2; // 需要转的圈数
        int mid = n / 2; // 矩阵中间的值
        int count = 1; // 给矩阵赋的值
        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int i,j;
        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 += 1;
        }

        //当n为奇数的情况
        if (n % 2) {
            res[mid][mid] = count;
        }
        return res;
    }
};