当前位置: 首页 > article >正文

【算法day2】数组:滑动窗口、前缀和及指针控制

题目引用

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

1.长度最小的子数组


给定一个含有 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

这里我们看一下题目:题目要求我们找到最短的 >=target 的数组并且返回它的长度。大家见到这种题目的时候可能下意识的就会想到我使用嵌套循环,从每个数组的位置出发寻找符合题意的数组并且不断更新最短的长度,这样当然是可以的,但是时间复杂度就是 O(N^2) 了。那么怎么减少时间复杂度呢?这就要引出今天的第一个算法: 滑动窗口

首先我们还是设立两个指针,一个快指针 fast ,一个慢指针 slow ,都设立在起点
初始化
然后定义 result=INT_MAXfastslow 的区间和为 sum=0 ,变化后的区间和为 tmp=0
定义

sum>=target 时,用 tmp 记录当前 fastslow 的长度,更新 result ,然后将末尾 slow 位置的值减掉, slow 向前走寻找新的子区间,直到fast到达末尾循环结束。
进入循环
循环结束
最后附上代码

int minSubArrayLen(int target, vector<int>& nums) {
        int slow=0;
        int result=INT_MAX;
        int sum=0;
        int tmp=0;
        for(int fast=0;fast<nums.size();fast++){
            sum+=nums[fast];
            while(sum>=target){
                tmp=(fast-slow+1);
                result=min(tmp,result);
                sum-=nums[slow++];
            }
        }

        return result==INT_MAX?0:result;
    }

值得注意的是,我们的sum有可能到循环结束都没有更新过result,所以最后返回时需要特判一下,避免这种情况。

区间和


题目描述
给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。
输入描述
第一行输入为整数数组 Array 的长度 n,接下来 n 行,每行一个整数,表示数组的元素。随后的输入为需要计算总和的区间下标:a,b (b > = a),直至文件结束。
输出描述
输出每个指定区间内元素的总和。
输入示例

5
1
2
3
4
5
0 1
1 3

输出示例

3
9

我们来分析一下题目
我们得到了一个长度为n的随机数组,需要计算从这个区间里面所有数的和,最简单的解法当然还是嵌套循环,每次从区间的左加到区间的右,但是依然需要经历两层循环,不美。
让我们看看怎么利用前缀和解决这个问题。
前缀和 就是从数组的第一个位置开始累加到当前位置的数值就叫做前缀和。那么我们怎么获取到前缀和呢?
很简单,在我们接受数据时额外定义一个数组和一个变量,用来记录当前位置的前缀和,而这个数组就叫做前缀和数组,当题目给出需要的区间和时,我们只需要将右边界所在的前缀和减去左边界所在的位置前一位的前缀和就能得出答案,当然如果左边界是0的话,我们直接取右区间数值即可。
以案例一为例
初始化
查询
可能有人会疑问,为什么要减左边界的前一位呢?
因为前缀和是从数组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++) {
        scanf("%d", &vec[i]);
        presum += vec[i];
        p[i] = presum;
    }

    while (~scanf("%d%d", &a, &b)) {
        int sum;
        if (a == 0) sum = p[b];
        else sum = p[b] - p[a - 1];
        printf("%d\n", sum);
    }
}

螺旋矩阵


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

题目

示例 1:

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

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

来说一下思路
题目只给我们一个n,要求我们返回已经旋转好的二维数组,那么我们发现数组会绕着外围一直旋转,直到转到数组中心,那么总共转几圈呢?
去掉中心只旋转了n/2 圈。
所以我们需要绕着数组一直旋转n/2圈,并且需要一个数每填一次就++,并且在内圈旋转时需要重新定位位置再次旋转,那么代码就不难了。

vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> vv(n,vector<int>(n,0));
        int x=0,y=0;
        int loop=n/2;
        int count=1;
        int offset=1;
        int i,j;
        while(loop--){
            i=x,j=y;
            for(;j<y+n-offset;j++){
                vv[i][j]=count++;
            }

            for(;i<x+n-offset;i++){
                vv[i][j]=count++;
            }

            for(;j>y;j--){
                vv[i][j]=count++;
            }

            for(;i>x;i--){
                vv[i][j]=count++;
            }

            x++,y++;
            offset+=2;
        }
        int mid=n/2;
        if(n%2) vv[mid][mid]=count;

        return vv;
    }

总结


当我们遇到数组中与区间有关的问题时,可以试试用滑动窗口和差分来解决问题,当然遇到实在解决不了的问题时,该模拟就模拟,找清楚逻辑和关键点,就能写出来啦~


http://www.kler.cn/a/414598.html

相关文章:

  • 【踩坑日记】【教程】如何在ubuntu服务器上配置公钥登录以及bug解决
  • JVM 常见面试题及解析(2024)
  • 鸿蒙面试 --- 性能优化
  • 阅读《基于蒙特卡洛法的破片打击无人机易损性分析》_笔记
  • 以达梦为数据库底座时部署的微服务页面报乱码,调整兼容模式
  • 常用元器件使用方法18:单节锂电池充电管理芯片XT4052的使用方法
  • 轻松解析 PDF 文档:深入了解 Python 的 pdfplumber 库
  • 原生html+css+ajax+php图片压缩后替换原input=file上传
  • 【配置】pycharm运行的项目如何修改名称(项目名称、模块名称)
  • 【AI系统】分布式通信与 NVLink
  • linux桌面qt应用程序UI自动化实现之dogtail
  • 3.5 Ui文件(界面文件)
  • Qml-TabBar类使用
  • 解决水库安全监测难题 长期无外接电源 低功耗设备智能化监测系统
  • Qt桌面应用开发 第八天(读写文件 文件编码 文件流)
  • 路由引入中次优路由和路由环路问题
  • Linux:进程的概念
  • c/c++ 用easyx图形库写一个射击游戏
  • 探索C/C++的奥秘之C++中的继承
  • 【C++】 list接口以及模拟实现
  • 【AI技术赋能有限元分析应用实践】pycharm终端与界面设置导入Abaqus2024自带python开发环境
  • 美畅物联丨如何通过ffmpeg排查视频问题
  • 直播实时美颜平台开发详解:基于视频美颜SDK的技术路径
  • go 和java 编写方式的理解
  • 数据安全与隐私保护:大数据时代的挑战与机遇
  • 华为海思2025届校招笔试面试经验分享