文章链接:977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II

视频链接:977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II

题目链接:977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II

第一想法

977.有序数组的平方

看到这道题的第一想法就是暴力求解,毕竟题目也很直白,我就只想到将元素都平方后排序。这种求解方法的时间复杂度为O(nlogn)。

(知识点:sort()函数的时间复杂度为O(nlogn).)

209.长度最小的子数组

首先我想到的是先将数组从大到小排序,然后对比num[0] 和 target,若num[0] > target,则返回1;若num[0] < target,则进行一个循环,找出数组的前几个数相加后第一次大于target。若全部相加后到不能大于target,则返回0。这一思路的时间复杂度为O(nlogn)

59.螺旋矩阵II

想用数学思想推导出规律,但是没有思路。

看完答案后的想法

977.有序数组的平方

这道题的答案式通过“双指针”的方法求解,时间复杂度是O(n)。思路是用两个指针,一个放在开始,一个放在最后,然后比较指针所在元素的平方后的结果,谁大就将其平方放入新数组的最后,以此类推。

209.长度最小的子数组

答案的思路是滑动窗口,本质也是双指针。开始将两个指针放在最开始的位置,然后移动一个指针(终点),从而得到一个区间,计算区间元素的总和,总和达到要求就更新reault。然后移动开始指针,也是计算区间长度,以此类推(注意区间长度要更新,为j - i + 1)。时间复杂度是O(n)。

59.螺旋矩阵II

这道题没有算法,主要是学习循环不变量,即对循环的处理规则要统一,如:若一边用左闭右开,则四条边都要用左闭右开。

遇到困难

977.有序数组的平方

这道题遇到的困难如下:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int k = nums.size() - 1;
        vector<int>result(nums.size(), 0); //注意数组的大小,以防数组越界
        for(int i = 0, j = k; i <= j;)
        // i++和j--是有条件的,应该放在循环内
        {
            if(abs(nums[i]) > abs(nums[j]))
            {
                result[k--] = nums[i] * nums[i];# 学会这种result[k--]的简写方式
                i ++;
            }
            else
            {
                result[k--] = nums[j] * nums[j];
                j --;
            }
        }
        return result;
    }
};

209.长度最小的子数组

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int result = 1e6; // 要设置一个很大的数
        int i = 0;
        int sum = 0;
        for(int j = 0; j < nums.size(); j++){
            sum += nums[j]; 
            while(sum >= target){
                result = min(result, j - i + 1); // 区间长度为j - i + 1
                sum -= nums[i]; // 和sum += nums[j] 结合起来求区间的和
                i++;
            }
        }
        return result == 1e6 ? 0 : result;
        // 如果result没有被赋值的话,就返回0,否则返回赋的值
    }
};

59.螺旋矩阵II

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> nums(n, vector<int>(n, 0));
        // 二维数组的定义! 

        int setx = 0;
        int sety = 0;
        int setoff = 1;
        int count = 1;
        int loop = n / 2; // 圈数(若为奇数,应在最后再对最中间的位置赋值)
        int i, j;
        int mid = n / 2;
        while(loop --){
            i = setx, j = sety; // 要定义,不然等会循环之间的i、j 无法共用

            // 都为左闭右开
            for(j; j < n - setoff; j ++){
                nums[i][j] = count++;
            }
            for(i; i < n - setoff; i++){
                nums[i][j] = count++;
            }
            for(; j > sety; j--){
                nums[i][j] = count++;
            }
            for(; i > setx; i--){
                nums[i][j] = count++;
            }
            setx++;
            sety++;
            setoff++;
        }
        if(n % 2 == 1)nums[mid][mid] = count;
        // 不能用if(n % 2 == 1)nums[i][j] = count;的原因:有些情况会数组越界。

        return nums;
    }
};

今日收获

今天花3个小时学了这三道题,学会了“双指针”“滑动窗口”以及“循环不变量”的重要性。