算法训练day2

209.长度最小的子数组: 给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其总和大于等于target的长度最小的子数组[nums_l, nums_{l+1}, ..., nums_{r-1}, nums_r],并返回其长度。如果不存在符合条件的子数组,返回0
(1)暴力求解法:利用两个循环,分别遍历子列的起始位置和终止位置;若检查到和>= target的子列,将其长度记为len;实时更新满足条件的最短子列长s。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum = 0, len = 0, s = nums.size()+10;
        for (int i = 0; i < nums.size(); i++){
            sum = 0;
            for (int j = i; j <nums.size(); j++){
                sum += nums[j];
                if (sum >= target) {
                   len = j-i+1;
                   break; 
                }
                else len = nums.size()+10;
            }
            if (s > len) s = len;
       }
       return s == nums.size() + 10 ? 0 : s;
    }
};

时间复杂度:O(n^2),这导致当n很大时超出时间限制;
空间复杂度:O(1)
(2)移动窗口解法:利用一个for循环遍历窗口终止位置,以其和sum是否大于target作为元素是否在窗口中的依据。若sum小于target,向后移动窗口终止位置;若sum大于target,向后移动窗口起始位置。注意移动时和sum的变化;并实时记录和比较子列长度。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum = 0, sublenth = 0, result = INT32_MAX;
        int i = 0; //star index
        for (int j = 0; j < nums.size(); j++){
            sum += nums[j];
            while(sum >= target){
                sublenth = j - i + 1;
                result = result < sublenth ? result : sublenth;
                sum -= nums[i++]; // 这里体现出滑动窗口的精髓之处,不断变更i
                continue;
            }
       }
       return result == INT32_MAX ? 0 : result;
    }
};

空间复杂度:O(n)
时间复杂度:O(1)
(3)解题困难:①不能准确判断移动窗口的起始位置i和终止位置j的设置;②尝试先固定子数组长度,再找满足和条件的子数组,最终还是要用两个循环。

59.螺旋矩阵: 给你一个正整数n,生成一个包含1n^2所有元素,且元素按顺时针顺序螺旋排列的n x n正方形矩阵matrix
(1)自我思路:n为奇数时有中心,为偶数时只有外圈;一圈四边,每边的元素数目只计算左闭右开区间内的元素。
(2)循环求解:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        std::vector<std::vector<int>> arr(n, std::vector<int>(n,0));
        int loop = n / 2; //记录要填充圈数,n为奇数时还需要单独处理中间位置
        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
        int mid = n/2;//记录中间位置
        int offset = 1;
        int count = 1;
        int i, j;
        while (loop--){
            i = startx; j = starty;
            for (j; j < n - offset; j++){ //j从0变到n-offset,n-offset未进入循环
                arr[i][j] = count++;
            }
            for (i; i < n - offset; i++) {//j从0变到n-1
                arr[i][j] = count++;
            }
            for (; j > startx; j--){ //j从n-offset 变到startx
                rr[i][j] = count++;
            }
            for (; i > starty; i--){ //i从n-offset 变到starty
                arr[i][j] = count++;
            }
            // 第二圈开始的时候,起始位置要各自加1
            startx++;
            starty++;
            // offset 控制每一圈里每一条边遍历的长度
            offset += 1;
        }
        if (n % 2) arr[mid][mid] = n*n;
        return arr;
    }
};

时间复杂度:O(n^2)
空间复杂度:O(1)
(3)主要困难:误用行列乘积给元素赋值;区间端点i与j的设置;
(4)收获:自增运算符有共同效果和细微区别。① 后缀自增:i++ 会先返回 i 的当前值,然后 i 的值增加1。② 前缀自增:++i 会先将 i 的值增加1,然后返回 i 的新值。例如

int i = 1;
int a = i++; // a = 1, i = 2
int b = ++i; // i = 3, b = 3
posted @   TomatoErn  阅读(385)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示