代码随想录算法训练营第二天|leetcode209.长度最小的子数组、leetcode59.螺旋矩阵、区间和问题

第一题.209. 长度最小的子数组 - 力扣(LeetCode)

最开始做这道题的时候没有仔细审题....,没看到是子序列,然后先对数组排序然后动态规划做了....简单问题复杂化了。。下次要好好读题呜呜呜😭并且题干要求不是正好等于target,题干说的是大于等于target。

思路A:暴力枚举。长度j-i+1(不要总因为加不加1的问题,而一直纠结。。。),然后当时做的时候res的初始值随便🫤设置的,,导师后面返回的时候出现了错误。。。。(我真是无语死了。。。)---》超时

 int minSubArrayLen(int target, vector<int> &nums) // 注意审题,这道题要找最短序列!
    {
        int res = INT32_MAX;         // 最终结果
        int sum = 0, len = 0; // 子序列的和,子序列长度
        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; // 更新长度
                    res = res < len ? res : len;
                    break;
                }
            }
        }
        return res == INT32_MAX ? 0 : res;
    }

思路B:滑动窗口
简而言之,就是不断调节子序列的起始位置和终止位置,从而得到我们想要的结果。

比如 2 3 1 2 4 3【7】 --》2 3 1 2 4 3--》2 3 1 2 4 3--》2 3 1 2 4 3--》2 3 1 2 4 3--》
        2 3 1
2 4 3--》 2 3 1 2 4 3--》2 3 1 2 4 3

int minSubArrayLen(int target, vector<int> &nums) // 注意审题,这道题要找最短序列!
    {
        int res = INT_MAX;
        int sum = 0, len = 0;
        int low = 0; // 滑动窗口起始位置
        for (int high = 0; high < nums.size(); high++)
        {
            sum += nums[high];
            while(sum >= target)//注意这里是while,不是if。因为高低指针都要不断的变更!!
            {
                len = high - low + 1;//取子序列长度
                res = res < len ? res : len;
                sum -= nums[low++];//体现出滑动窗口的精髓!!不断变更low(子序列起始位置)
            }
        }
        return res == INT_MAX ? 0 : res;
    }

注意⚠️,时间复杂度是O(n),因为主要是看每个元素被操作的次数。每个元素进去一次出去一次,O(2n)。

第二题:59. 螺旋矩阵 II - 力扣(LeetCode)

一入循环深似海,秋招offer say byebye~~~

思路:第一要注意点是边界处理问题!!全程保持一致:左闭右开
           第二是循环次数的问题 n/2
           第三是那几个变量赋值问题(我最开始这里完全搞混了,offset也没有引入,然后全程写的代码像💩一样冗余。然后循环之后变量更新,startx和starty++,这里误写成了i和j,我可真逆天😅)

    vector<vector<int>> generateMatrix(int n)
    {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int loop = n / 2;           // 表示转的圈数,因为转一圈减2,2x=n.
        int startx = 0, starty = 0; // 表示每一圈的起始位置
        int offset = 1;             // 表示每一圈的偏移量
        int count = 1;
        int i = 0, j = 0;
        while (loop--) // 循环的时候要保持左闭右开!
        {
            i = startx;
            j = starty;
            for (j; j < n - offset; j++)
            {
                res[i][j] = count++;
            }
            for (i; i < n - offset; i++)
            {
                res[i][j] = count++;
            }
            for (j; j > starty; j--)
            {
                res[i][j] = count++;
            }
            for (i; i > startx; i--)
            {
                res[i][j] = count++;
            }
            startx++; // 每转完一圈,初始值加1.
            starty++;
            offset++;
        }
        if (n % 2 == 1)
            res[n/2][n/2] = count; // 当n为奇数的时候,会剩下一个中间的数,需要单独赋值。
        return res;
    }

第三题 区间和 问题---前缀和
题目描述:给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。
比如1 2 3 4 5。求下标0和1区间元素。或者求下标1和3之间的元素。

思路1:暴力求解

for(int i = a;i<=b;i++) sum+=vec[i];

思路2:区间和求解方法

p[1] = vec[0]+vec[1];  p[3] =vec[0] + vec[1] + vec[2] + vec[3]; 
p[3]-p[1] = vec[2]+vec[3]。我们发现少一个数字vec[1],所以如果要求[1,3]之间的区间和,应该是p[3]-p[0];

#include <iostream>
#include <vector>
using namespace std;
int main() {
    int n, a, b;
    cin >> n;
    vector<int> vec(n);
    vector<int> p(n);
    int presum = 0;
    for (int i = 0; i < n; i++) {
        cin >> vec[i]; //scanf("%d",&vec[i]);
        presum += vec[i];
        p[i] = presum;
    }

    while (cin >> a >> b) { //while(~scanf("%d%d",&a,&b)){
    //这里注意scanf的返回值是读入元素的个数。
        int sum;
        if (a == 0) sum = p[b];
        else sum = p[b] - p[a - 1];
        cout << sum << endl; //printf("%d/n",sum);
    }
}

注⚠️:C++面对大量数据的时候,最好用scanf和printf,耗时会小很多。如上所示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值