前缀和模板算法

news2024/10/6 22:23:19

一)模板前缀和

【模板】前缀和_牛客题霸_牛客网 (nowcoder.com)

前缀和:快速的得出数组中某一段连续区间的和

暴力破解的话需要从头到尾的进行遍历,时间复杂度就可以达到O(N),而前缀和时间复杂度是可以达到O(1)的

第一步:预处理创建出一个前缀和数组dp,这个数组和原始数组规模是同等大小的

dp[i]就表示从[1,i]区间内所有数组的和

1到N区间内的和和1到L-1区间内的和本质上来说是同一类问题,研究问题的时候发现是同一类问题,我们就可以把这同一类问题抽象成状态表示,用动态规划的思想来进行解决

假设dp[3]表示的就是从1位置到3位置的所有元素的和,就是1+4+7=12

所以状态转移方程就是:dp[i]=dp[i-1]+array[i];

第二步:使用前缀和数组解决问题:

dp[i]=dp[r]-dp[l-1]

细节问题:在题干中下标为什么从1开始进行计数?

因为如果题目中给定的范围是0-2,那么势必会访问到dp[-1]此时dp表就会出现下标越界访问的情况


public class Main {
    public static void main(String[] args) {
//1.输入数据
        Scanner scanner = new Scanner(System.in);
        int n=scanner.nextInt();
        int count=scanner.nextInt();
         long[] array=new long[n+1];
        for(int i=1;i<=n;i++){
            array[i]=scanner.nextLong();
        }
//2.预处理一个前缀和数组
        long[] dp=new long[n+1];
        for(int i=1;i<=n;i++){
            dp[i]=array[i]+dp[i-1];
        }
//3.使用前缀和数组
        while(count>0){
            count--;
            int left=scanner.nextInt();
            int right=scanner.nextInt();
            System.out.println(dp[right]-dp[left-1]);
        }
    }
}

二)二维前缀和

【模板】二维前缀和_牛客题霸_牛客网 (nowcoder.com)

一)预处理出来一个前缀和矩阵:这个前缀和矩阵必须和原始矩阵规模大小是一样的

dp[i][j]表示从(1,1)这个位置到(i,j)这段区间内,所围成的矩形的,这段区间内所有元素的和

dp[i][j]=dp[i-1][j]+array[i][j]+dp[i][j-1]-dp[i-1][j-1] 

result=dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]

自己画图可以不花正方形,可以直接画数进行分析

import java.util.Scanner;
import java.util.Arrays;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
//1.先进行处理数据的输入
 Scanner scanner=new Scanner(System.in);
  int m=scanner.nextInt();
  int n=scanner.nextInt();
  int count=scanner.nextInt();//初始化输入次数
  long[][] array=new long[m+1][n+1];
  for(int i=1;i<=m;i++){
    for(int j=1;j<=n;j++){
        array[i][j]=scanner.nextInt();
    }
  }
//2.创建dp表进行填表,使用前缀和数组
long[][] dp=new long[m+1][n+1];
  for(int i=1;i<=m;i++){
    for(int j=1;j<=n;j++){
        dp[i][j]=dp[i-1][j]+array[i][j]+dp[i][j-1]-dp[i-1][j-1];
    }
  }
//2.进行返回结果,使用前缀和数组
   while(count>0){
    int x1=scanner.nextInt();
    int y1=scanner.nextInt();
    int x2=scanner.nextInt();
    int y2=scanner.nextInt();
long result=dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1];
// System.out.println(Arrays.deepToString(dp));
  System.out.println(result);
  count--;
}
    }
}

三)寻找数组的中心下标

724. 寻找数组的中心下标 - 力扣(Leetcode)

暴力枚举:每一次枚举一个中间下标i的时候,都需要把(0-i-1)之间的数进行相加,还需要把(i,array.length)之间的数进行相加一遍,可见时间复杂度会变得非常的高

 一)定义一个状态表示:

f[i]表示从0号位置到i-1位置,所有元素的和

g[i]表示从i+1号位置到n-1位置,所有元素的和

二)根据状态表示推导状态转移方程

f[i]=f[i-1]+array[i-1]

g[i]=g[i+1]+array[i+1]

三)初始化(防止发生数组越界)

f[0]=0,g[n-1]=0

四)填表顺序:

f表:从左向右

g表:从右向左

class Solution {
    public int pivotIndex(int[] array) {
        int n=array.length;
        int[] f=new int[n];//f[i]表示从0号位置到i位置数组中这段区间内的和
        int[] g=new int[n];//g[i]表示从i+1号位置到n-1位置数组中这段区间的和
        //最后只是需要得出f[i]=g[i]即可
        f[0]=0;//填写到f[0]位置的时候数组就会发生越界
        g[n-1]=0;//因为填写到n-1位置的时候数组就会发生越界
        for(int i=1;i<n;i++){//f从前向后进行填表
            f[i]=f[i-1]+array[i-1];
        }
        for(int i=n-2;i>=0;i--){//g从后向前填表
            g[i]=g[i+1]+array[i+1];
        }
      for(int i=0;i<n;i++){
          if(f[i]==g[i]){
              return i;
          }
      }
      return -1;
    }
}

四)除自身以外数组的乘积:

238. 除自身以外数组的乘积 - 力扣(Leetcode)

一)定义一个状态表示:

f[i]表示从0-i-1位置这段区间所有元素的乘积

g[i]表示从i+1位置开始到n-1这段区间内所有元素的乘积

二)根据状态表示推导状态转移方程:

f[i]=f[i-1]*array[i-1](0号位置的元素到i-2位置的元素的乘积再乘上array[i-1]位置的元素即可)

g[i]=g[i+1]*array[i+1](从i+2号位置的元素到n-1号位置的元素的乘积再乘以i+1号位置的元素)

三)进行初始化操作:f[0]=1,g[n-1]=1

四)填表顺序:f表从左向右填,g表从右向左填

class Solution {
    public int[] productExceptSelf(int[] array) {
//1.创建前缀积以及后缀积数组
        int[] f=new int[array.length];
        int[] g=new int[array.length];
        int[] ret=new int[array.length];
        f[0]=1;
        g[array.length-1]=1;
//2.初始化
        for(int i=1;i<array.length;i++){
            f[i]=f[i-1]*array[i-1];
        }
        for(int i=array.length-2;i>=0;i--){
            g[i]=g[i+1]*array[i+1];
        }
        for(int i=0;i<array.length;i++){
            ret[i]=f[i]*g[i];
        }
     return ret;
    }
}

五)和为K的子数组

剑指 Offer II 010. 和为 k 的子数组 - 力扣(Leetcode)

1)暴力解法:

1)采取枚举策略,定义两个变量i和j,i每次固定不动,j一直向后走,走一步加array[j],直到遇到sum和等于k

2)但是此时j应该继续向后走,直到j把整个数组遍历完成,因为有可能会出现j遇到整数又遇到负数的情况,此时应该还是让sum=sum+array[j],如果sum==k,应该再次让count++),此时的时间复杂度就是O(N^2)

不能使用双指针优化:必须有单调性

class Solution {
    public int subarraySum(int[] array, int k) {
        int count=0;
        for(int i=0;i<array.length;i++){
            int sum=0;
            for(int j=i;j<array.length;j++){
                sum=sum+array[j];
                if(sum==k) count++;
            }
        }
    return count;
    }
}

2)前缀和:

2.1)以i位置为结尾的所有子数组(一定是包含i位置的元素的)先找到和为K的子数组有多少个,然后把所有情况都进行累加起来

2.2)从而就转化成了在[0~i-1]区间内,i前面有多少个前缀和等于sum[i]-k

如果真的采用上面的思路进行遍历查找(0-i)区间内有多少前缀和等于K,array[right]-array[left-1]=K,那么最终的时间复杂度就是O(N^2)+K,时间复杂度又会飙升 

class Solution {
    public int subarraySum(int[] array, int k) {
        //dp[i]表示从0号位置到i号位置所有元素的和,开始初始化dp数组
        int[] dp=new int[array.length+1];
        dp[0]=0;
        for(int i=1;i<=array.length;i++){
            dp[i]=dp[i-1]+array[i-1];
        }
        System.out.println(Arrays.toString(dp));
        int count=0;
        //1.使用前缀和注意下标的映射关系
//2.注意新的dp数组left到right区间内的和有多少等于k是dp[right]-dp[left-1]是[left,right]区间内的和
        for(int left=1;left<=array.length;left++){
            for(int right=left;right<=array.length;right++){
                if(dp[right]-dp[left-1]==k) count++;
            }
        }
        return count;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/757201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RTMP简介

简介 RTMP协议是Real Time Message Protocal(实时传输协议的缩写)&#xff0c;同时Adobe公司提供的一种应用层协议&#xff0c;用来解决多没意思数据流传输的 多路复用和分包问题。 RTMP是应用层协议&#xff0c;采用TCP来保证可靠的传输在TCP完成握手连接建立后&#xff0c…

【动手学深度学习】--03.多层感知机MLP

文章目录 多层感知机1.原理1.1感知机1.2多层感知机MLP1.3激活函数 2.从零开始实现多层感知机2.1初始化模型参数2.2激活函数2.3 模型2.4损失函数2.5训练 3.多层感知机的简洁实现3.1模型3.2训练 多层感知机 1.原理 官方笔记&#xff1a;多层感知机 1.1感知机 训练感知机 收敛定…

SEO 基础知识? 2023学习SEO最佳指南

文章目录 搜索引擎优化基础知识什么是搜索引擎优化&#xff1f;为什么搜索引擎优化很重要&#xff1f;SEO有什么好处&#xff1f;如何做搜索引擎优化关键词研究内容优化网站结构优化&#xff08;页面SEO&#xff09;外部链接优化移动优化分析和迭代(技术SEO) 为 SEO 成功做好准…

蓝牙技术|低功耗蓝牙和LE Audio助力游戏设备行业发展

去年&#xff0c;蓝牙技术联盟官方宣布推出LE Audio&#xff0c;它以BLE为基础&#xff0c;旨在更好地兼顾音频质量和低功耗&#xff0c;以在多种潜在应用中显著增强用户体验。这在游戏行业中引起了轰动&#xff0c;由于其延迟显著降低&#xff0c;LE Audio在增强游戏体验方面展…

单片机第一季:零基础9——直流电机和步进电机

目录 1&#xff0c;直流电机 2&#xff0c;步进电机 1&#xff0c;直流电机 直流电机是指能将直流电能转换成机械能&#xff08;直流电动机&#xff09;或将机械能转换成直流电能&#xff08;直流发电机&#xff09;的旋转电机。它是能实现直流电能和机械能互相转换的电机。…

Jenkins的安装部署以及基本使用

前言&#xff1a; 今天有空大概记录的一个作为一个测试人员日常中Jenkins的使用。 一、环境准备 在安装使用Jenkins前我们要先安装jdk&#xff0c;这里博主选择的是jdk11。我们先删除旧的jdk然后安装全新的jdk。 1、先看下当前我们的jdk版本。 2、查看jdk安装路径&#xff1…

Simulink仿真模块 - Unit Delay

Unit Delay:将信号延迟一个采样期间 在仿真库中的位置为:Simulink / Discrete HDL Coder / Discret 模型为: 双击模型打开参数设置界面,如图所示: 说明 Unit Delay 模块按指定的采样期间保持和延迟输入。当放置于迭代子系统中时,该模块将其输入保持并延迟一个迭代。此…

视频文件一键批量去除水印需要用到什么剪辑软件

刚接触视频剪辑这个行业的小伙伴在找视频素材的过程中&#xff0c;如果发现视频带有水印是不是非常头疼&#xff0c;不知道怎么处理这件事。那今天我们就来聊聊怎么才能快速批量去除视频的水印呢&#xff1f;今天小编给大家带来一个好方法&#xff0c;一起来看看吧。 一、首先我…

Redis实战案例17-Redisson可重入的原理

可重入原理分析 为什么自定义的Redis实现分布式锁不能实现可重入 method1中调用了method2方法&#xff0c;属于是同一线程内的操作&#xff0c;但是当method1中获取了锁之后&#xff0c;method2中就无法获取锁了&#xff0c;这就是同一线程无法实现可重入&#xff1b; 如何解决…

Windows上查看服务器上tensorboad内容

文章目录 前言一、SSH的设置二、tensorboard命令 前言 本篇文章是针对于局域网内的服务器的tensorboard可视化&#xff0c;由于设置方式稍微有点复杂&#xff0c;导致我每次隔了一段时间之后&#xff0c;就不知道该怎么查看tensorboard了&#xff0c;每次都要百度搜一大堆资料…

安达发|选择APS排程系统一定要注意这五大问题

随着信息技术的迅速发展&#xff0c;云计算已成为企业信息化建设的重要领域。在云计算中&#xff0c;aps是企业服务器环境中常见的虚拟化解决方案。然而&#xff0c;市场上有许多aps系统可供选择&#xff0c;企业在选择合适的系统时需要综合考虑多种因素。本论文将从这个五个角…

nacos十分钟快速搭建

简介 nacos是阿里巴巴开源的微服务基础组件&#xff0c;充当微服务架构中的配置中心和注册中心&#xff0c;nacos可单独作为配置中心或者注册中心 目录结构 bin&#xff0c;bin工具 conf&#xff0c;配置文件 target&#xff0c;nacos的jar包 安装 机器环境&#xff1a;cen…

清洁机器人规划控制方案

清洁机器人规划控制方案 作者联系方式Forrest709335543qq.com 文章目录 清洁机器人规划控制方案方案简介方案设计模块链路坐标变换算法框架 功能设计定点自主导航固定路线清洁区域覆盖清洁贴边沿墙清洁自主返航回充 仿真测试仿真测试准备定点自主导航测试固定路线清洁测试区域…

Redis数据类型 — Hash

目录 Hash内部实现 源码片段 Hset执行函数 创建hash对象 尝试转换存储空间的编码 遍历把键值对根据存储空间格式进行存储起来 Hash 是一个键值对&#xff08;key - value&#xff09;集合&#xff0c;Hash 特别适合用于存储对象。 Hash内部实现 Hash 类型的底层数据结构…

[Error] graphics.h: No such file or directory

原因&#xff1a;系统编译器找不到graphics.h文件&#xff0c;graphics.h这个文件就类似Java里面的jar包&#xff0c;也相当于Python里面pip安装的依赖包&#xff0c;graphics.h是样式设计文件&#xff0c;需要放到编译的文件夹里面 解决办法&#xff1a; 1.从该网址下载graphi…

Talk | 天津大学博士生赵煜:从平面图像中理解空间语义 - 视觉空间位置描述

本期为TechBeat人工智能社区第512期线上Talk&#xff01; 北京时间7月12日(周三)20:00&#xff0c; 天津大学博士生—赵煜的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “从平面图像中理解空间语义-视觉空间位置描述”&#xff0c;他与大家探讨了…

Html基础知识学习——兼容问题与解决方法(十六)

文章目录 1.计算一定要精确&#xff0c;不要让内容的宽高超出我们设置的宽高&#xff0c;在IE6下内容会撑开设置好的宽高2.元素浮动&#xff0c;宽度需要内容撑开&#xff0c;就给里面的块元素都加浮动3.在ie6.ie7下元素要浮动并在同一行 就给这些元素都加浮动4.注意标签嵌套规…

数学建模-典型相关分析

上节回顾 论文&#xff1a;常州大学一等奖淡水养殖… 要进行 pearson 相关系数 画散点图、折线图看是否相关检验正态分布满足上述&#xff0c;利用pearson相关系数 刚开始推导不会没关系&#xff0c;会应用就行&#xff0c;推导过程略&#xff0c;之后学习了后续知识&#xff…

JS基础教程

一、JS简介 1.1 学习内容 JavaScript&#xff08;简称“JS”&#xff09; 是一种具有函数优先的轻量级&#xff0c;解释型或即时编译型的编程语言。它是作为开发Web页面的脚本语言而出名&#xff0c;JavaScript 基于原型编程、多范式的动态脚本语言&#xff0c;并且支持面向对…

复习之系统定时任务及延迟任务

一、延迟任务&#xff08;一次性的&#xff09; 1. 延迟任务的设定 at 时间 &#xff1a;具体时间设定延迟任务 设定成功后“ ctrl d "发起任务&#xff0c;" ctrl c " 取消。 at -l &#xff1a;查看延迟任务at -c 1 &#xff1a;查看序号为1 的延迟…