Day2|209.长度最小的子数组|螺旋矩阵|区间和

209.长度最小的子数组

题目链接:

https://leetcode.cn/problems/minimum-size-subarray-sum/description/

这里是卡哥原文链接,讲的清晰明了: 

https://www.programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html#%E6%80%9D%E8%B7%AF

暴力解法:

看了示例默写的代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
    int result = INT32_MAX;
    int sum = 0;
    int sublength = 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) {
                sublength = j - i + 1;
                result = result < sublength ? result : sublength;
                break;
            }
        }
    }
    return result == INT32_MAX ? 0 : result;
    }
};

代码错误:

进行判断是否赋值,if(sum > target) 应该是if(sum >= target),因为没好好读题,题目中说的是  找出该数组中满足其总和大于等于 target 的长度最小的子数组,可恶。。。。

代码分析:

  1. 两个循环,第一个循环表示起始位置,第二个循环表示从起始位置开始,不断向后遍历数组,并通过if判断是否赋值,注意满足判断条件后,应及时break;在第一层循环中应该重置sum的值;给result赋值的时候,将result的值与新的sublength的值作比较,返回小的那一个值。
  2. 关于INT32_MAX:INT_MAX 和 INT_MIN 是 C++ 的两个宏,代表了整型变量能够存储的最大正整数和最小负整数,分别为 2147483647 和 -2147483648,这两个宏在头文件 <limits.h> 中定义。
  3. 在本代码中,用INT32_MAX表示result(数组长度的最大值),然后不断地用sublength和result比较,如果符合题中条件,将会给result赋值,循环结束之后,如果result的值还是INT32_MAX,说明没有赋值,返回0,如果result的值是别的数,则返回result的值。
  4. 关于result和sublength,二者都是求得的数组的长度,sublength是一次循环操作的实时长度值,result是经过比较筛选出来的最小长度

 滑动窗口

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

示例代码:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
    int result = INT32_MAX;
    int sum = 0;
    int sublength = 0;
    int i = 0;
    for (int j = 0; j < nums.size(); j++) {
        sum += nums[j];
        while (sum >= target) {
            sublength = j - i + 1;
            result = result > sublength ? sublength : result;
            sum -= nums[i++]; 
        }
    }
    return result == INT32_MAX ? 0 : result;
    }
};

这里借助卡哥的两个图辅助分析:c8989b01756b49a98018a343c89d9971.gif

28f2868657fc49d590057ef8bc33c6d5.png

思路:

本题的滑动窗口法和双指针法有异曲同工之妙。  窗口指的是满足条件的最小子数组,窗口的起始位置移动,也就是当满足sum>=target,终止位置不动,起始位置动,即sum -= nums[i++],动到不满足循环条件,终止位置再开始动,   再计算sum直到结束。

59.螺旋矩阵

直接看题解:https://www.programmercarl.com/0059.螺旋矩阵II.html#思路

代码示例:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n,vector<int>(n,0));
        int startx = 0;
        int starty = 0;
        int count = 1; //先使用后加加
        int loop = n / 2;
        int mid = n / 2;
        int offset = 1;
        int i,j;
        
        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 > starty; j--) {
                res[i][j] = count++; 
            }
            for (; i > startx; i--) {
                res[i][j] = count++;
            }
            starty++;
            startx++;
            offset++;
        }
        if(n%2==1) {res[mid][mid] = n * n;}
        return res;

    }
};

代码疑点:

  1. 不会用vector创建二维数组

代码分析:

  1. 核心:注意循环不变量的使用,始终遵循左闭右开,按照矩阵规则设计i, j,(i是行,j是列)
  2. res[i][j] = count++; 这里的count先使用赋值再加加,所以count的起始值是1
  3. int offset = 1;for (j; j < n - offset; j++) ,offset是为了控制右边界,例如n=3,那第一次循环j的终点在1,(因为数组的起始下标是0)这里附上卡哥的图
  4. for (; j > starty; j--)这里不定义j是因为在上次循环中,j的值已经到了最后一列,直接循环即可。
  5. 每进行一圈赋值结束后,startx和starty都要加加,看图可知,而且赋值的圈数要减减,这也是循环的条件
  6. 注意n是奇数偶数

d75a4f61c07b4699bacc2a832d2c544c.png

区间和

题目链接:

https://kamacoder.com/problempage.php?pid=1070

题目描述

给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。

输入描述

第一行输入为整数数组 Array 的长度 n,接下来 n 行,每行一个整数,表示数组的元素。随后的输入为需要计算总和的区间,直至文件结束。

输出描述

输出每个指定区间内元素的总和。

输入示例

5
1
2
3
4
5
0 1
1 3

输出示例

3
9

数据范围:

0 < n <= 100000

这个题的主要目的是熟悉acm模式,并且学会使用vector的基本操作

方法:前缀和:通过vector创建两个数组,要统计 vec[i] 这个数组上的区间和,我们先做累加,即 p[i] 表示 下标 0 到 i 的 vec[i] 累加 之和,如图,例如要计算2到5的区间和,就用p[5]-p[1]

推导:

p[1] = vec[0] + vec[1];

p[5] = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5];

p[5] - p[1] = vec[2] + vec[3] + vec[4] + vec[5];

代码实现:

#include<iostream>
#include<vector>
using namespace std;
int main() {
    int n,a,b;
    int presum = 0;
    cin >> n;
    vector<int> vec(n);
    vector<int> p(n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &vec[i]);
        presum += vec[i];
        p[i] = presum;
    }
    while (scanf("%d%d", &a, &b) == 2) {
        int sum = 0;
        if (a == 0) sum = p[b];
        else sum = p[b] - p[a-1];
        printf("%d\n", sum);
    }
    return 0;
}

注意:最后进行判断:a==0;C++ 代码 面对大量数据 读取 输出操作,最好用scanf 和 printf,耗时会小很多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值