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

198 阅读3分钟

977. 有序数组的平方

题目(著作权归领扣网络所有)

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。  

示例 1:

输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100] 示例 2:

输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121]  

提示:

1 <= nums.length <= 104 -104 <= nums[i] <= 104 nums 已按 非递减顺序 排序  

进阶:

请你设计时间复杂度为 O(n) 的算法解决本问题。

思考

首先观察可知这是一个有序数组,那么平方的最大值一定是在数组两端。据此,再使用双指针,逐个比较,最终得到原数平方的递增数组。

代码

    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> tmp(nums.begin(), nums.end());
        int index1 = 0;
        int index2 = tmp.size() - 1;
        int i = nums.size() - 1;
        //优化 记 n1 = tmp[index1] * tmp[index1] n2 = tmp[index2] * tmp[index2]会简洁一些
        while(index1 <= index2){
            if(tmp[index1] * tmp[index1] > tmp[index2] * tmp[index2]){
               nums[i--] = tmp[index1] * tmp[index1];
               index1++;
            }
            else{
                nums[i--] = tmp[index2] * tmp[index2];
                index2--;
            }
        }
        return nums;
    }

209. 长度最小的子数组

题目(著作权归领扣网络所有)

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。 示例 2:

输入:target = 4, nums = [1,4,4] 输出:1 示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0  

提示:

1 <= target <= 109 1 <= nums.length <= 105 1 <= nums[i] <= 105  

进阶:

如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

思考

自己做没什么思路,之前做过一次也想不起来了,所以复习太重要了。暴力解法是挨个从不同的元素开始,比较得出最小符合条件的字串长度。滑动窗口比较巧妙,后面一次是基于前一次的基础上进行的,注意最外层循环变量要作为滑动窗口的右侧,也就是终点,这样实现逻辑比较清晰。

代码

   //滑动窗口法
    int minSubArrayLen(int target, vector<int>& nums){
        int sum = 0;
        int result = INT32_MAX;
        int i = 0;
        for(int j =0; j < nums.size(); j++){
            sum += nums[j];
            while(sum >= target){
                int subLength = j - i + 1;
                result = subLength < result ? subLength : result;
                sum -= nums[i++];
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
    //暴力解法
    // int minSubArrayLen(int target, vector<int>& nums) {
    //     int result =INT32_MAX;        
    //     for(int i = 0; i < nums.size(); i++){
    //         int sum = 0;
    //         for(int j = i; j < nums.size(); j++){
    //             sum += nums[j];
    //             if(sum >= target){
    //                 int subLength = j - i + 1;
    //                 result = result < subLength ? result : subLength;
    //                 break;
    //             }
    //         }
    //     }
    //     return result == INT32_MAX ? 0 : result;
    // }

59. 螺旋矩阵 II

题目(著作权归领扣网络所有)

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

 示例 1:

输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]] 示例 2:

输入:n = 1 输出:[[1]]  

提示:

1 <= n <= 20

思考

螺旋矩阵这一题对于自己难度也比较大,一开始连思路也不清晰。看了卡哥的讲解视频,了解到了循环不变量这个技巧,就是要保证处理矩阵每一条边的规则要一样,不然代码逻辑就不好写。代码写的过程中出现了一些bug,经过打断点和查看变量,发现问题所在,并以注释的形式记录在了代码中。

代码

    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> matrix(n, vector<int>(n, 0));
        //错误3:vector<vector<int>> matrix; 不初始化,赋值时会报错就会报错
        int startx = 0;
        int starty = 0;
        int offset = 1;
        int count = 1;
        int loop = n / 2;
        while(loop--){//错误4:写成n / 2是错误的,就会死循环
            //优化1:for循环还是可以写的更简洁的,如下面随想录的写法
            // i = startx;
            // j = starty;
            // // 下面开始的四个for就是模拟转了一圈
            // // 模拟填充上行从左到右(左闭右开)
            // 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++;
            // }

            for(int j = starty; j < n - offset; j++){
                matrix[startx][j] = count++;
            }
            for(int i = startx; i < n - offset; i++){
                matrix[i][n - offset] = count++; 
            }
            for(int j = n - offset; j > starty; j--){//错误2: j >= starty是错误的,因为为遵循循不变量原则
                matrix[n - offset][j] = count++; 
            }
            for(int i = n - offset; i > startx; i--){
                matrix[i][starty] = count++; 
            }
            startx++;
            starty++;
            offset++;
        }   
        if(n % 2 == 1)
            matrix[n / 2][n / 2] = n * n; //错误1 注意数组下标和位序的关系:n / 2 - 1是错误的
        return matrix;    
    }