前缀和代码解析

news/2025/2/26 5:55:22

前缀和是指数组一定范围的数的总和,常见的有两种,一维和二维,我会用两道题来分别解析

一维

DP34 【模板】前缀和

题目:

题目解析:

暴力解法

直接遍历数组,遍历到下标为 l 时,开始进行相加,直到遍历到下标为 r ,最后返回总和.这样做的时间复杂度为: O(n)

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        //接收数据
        int n = in.nextInt(),q=in.nextInt();
        int[] arr = new int[n+1];
        arr[0]=0;
        for(int i=1;i<=n;i++){
            arr[i]=in.nextInt();
        }
        while(q>0){
            int l=in.nextInt(),r=in.nextInt();
            int sum = 0;
            for(int i =l;i<=r;i++){
                sum+=arr[i];
            }
            System.out.println(sum);
            q--;
        }
    }
}

虽然代码本身是没有问题的,但是在某些情况下会运行超时

优化

对于前缀和来说,我们可以使用动态规划的部分知识来进行解决,总共分为两步

1.预处理前缀和数组

我们创建一个新的数组,数组的规模和原数组保持一致,如图:

 

但是在我们求dp数组时,难免会对原数组重复计算,这样会增加代码的耗时,有没有简洁的方法呢?

当然是有的,从dp的获得式中我们可以发现, dp[i] = dp[i-1]+arr[i] 

2.使用数组

最后我们就可以返回值, 也就是上文提到的 dp[r]-dp[l-1] 

代码

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    // 注意 hasNext 和 hasNextLine 的区别
    //接收数据
    int n = in.nextInt(),q=in.nextInt();
    int[] arr = new int[n+1];
    arr[0] = 0;
    for(int i=1;i<arr.length;i++){
        arr[i] = in.nextInt();
    }
    //计算动态数组
    long[] dp = new long[n+1];
    dp[0] = 0;
    for(int i=1;i<dp.length;i++){
        dp[i]=dp[i-1]+arr[i];
    }
    //处理结果
    while(q>0){
        int l=in.nextInt(),r=in.nextInt();
        System.out.println(dp[r]-dp[l-1]);
        q--;
    }
}

在代码中我们可以看到,我们为数组增加了辅助节点,也就是 arr[0] 和 dp[0] ,那么为什么要增加这个辅助节点呢?或者为什么在使用数组的时候,下标要从1开始计算呢?

因为如果我们没有辅助节点或者从0开始计算,那么当 l (求前缀和的起点) 为 0 时,那么 dp[l-1] 就会越界

运行结果

二维

二维数组也就是矩阵,在计算矩阵的前缀和时,我们需要更注意一些细节

例题: DP35 【模板】二维前缀和

这道题大致与上一道题相似,所以就不进行暴力解法了,直接开始解析

也就是说,这里我们已经得到了用于动态规划的数组 dp ,我们只要再将dp中的值进行计算,就可以得到最后的值了

所以,最后要得出的答案就是 D = dp[x2][y2] -dp[x1-1][y1] -dp[x1][y1-1] +dp[x1-1][y1-1] 

代码:

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    // 注意 hasNext 和 hasNextLine 的区别
    //获取数据
    int n = in.nextInt(),m=in.nextInt(),q=in.nextInt();
    int[][] arr = new int[n+1][m+1];
    for(int i=1;i<n+1;i++){
        for(int j=1;j<m+1;j++){
            arr[i][j] = in.nextInt();
        }
    }

    //设置动态矩阵
    long[][] dp = new long[n+1][m+1];
    for(int i=1;i<n+1;i++){
        for(int j=1;j<m+1;j++){
            dp[i][j] = dp[i-1][j]+dp[i][j-1]+arr[i][j]-dp[i-1][j-1];
        }
    }
    //得出答案
    while(q>0){
        int x1=in.nextInt(),y1=in.nextInt(),x2=in.nextInt(),y2=in.nextInt();
        System.out.println(dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]);
        q--;
    }
}

 运行结果:


http://www.niftyadmin.cn/n/5868116.html

相关文章

[字节青训_AI对话框]SSE交互规范、自定义事件、前后端数据传递、状态监听、连接和断开详解

1.SSE基础 以下是关于 Server-Sent Events (SSE) 的前后端交互规范、常见方法及自定义扩展的完整指南: 一、SSE 交互规范 1. 基础协议 HTTP 协议:基于 HTTP/1.1 长连接,响应头需包含:Content-Type: text/event-streamCache-Control: no-cacheConnection: keep-alive2. 数…

deepseek部署:ELK + Filebeat + Zookeeper + Kafka

## 1. 概述 本文档旨在指导如何在7台机器上部署ELK&#xff08;Elasticsearch, Logstash, Kibana&#xff09;堆栈、Filebeat、Zookeeper和Kafka。该部署方案适用于日志收集、处理和可视化场景。 ## 2. 环境准备 ### 2.1 机器分配 | 机器编号 | 主机名 | IP地址 | 部署组件 |-…

WIFI的SSID超长,隐藏,重复 (2.4G和5G差异)

目录 1、2.4G和5G的频率范围‌ 2、2.4G和5G的差异‌&#xff1a; 3、隐藏ssid显示为\x00 4、 重复的ssid名称 扩展 前言 最近处理wifi设备时发现&#xff0c;小小一个ssid就有超多的问题。 不是中文转义就是超长&#xff0c;现在还发现空字符的&#xff0c;原来时对方路由隐藏了…

【实战 ES】实战 Elasticsearch:快速上手与深度实践-1.1.1对比传统数据库与搜索引擎(MySQL vs ES)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 为什么选择Elasticsearch&#xff1f;——从MySQL到Elasticsearch的深度对比引言一、核心概念对比1. 数据模型差异2. 查询语言对比 二、适用场景对比1. MySQL的典型场景2. E…

CPU多级缓存机制

目录 一、前置知识 ---- CPU的核心 1.1. 单核与多核CPU 二、CPU多级缓存机制 三. 缓存的基本结构/缓存的存储结构 四、CPU缓存的运作流程/工作原理 五、CPU多级缓存机制的工作原理【简化版】 5.1. 缓存访问的过程 (5.1.1) L1缓存&#xff08;一级缓存&#xff09;访问 …

Nginx的安装和部署以及Nginx的反向代理与负载均衡

Nginx的安装和部署以及Nginx的反向代理与负载均衡 1. 本文内容 Nginx的安装Nginx的静态网站部署Nginx的反向代理与负载均衡&#xff0c;配置反向代理与负载均衡 2. Nginx的安装与启动 2.1 什么是Nginx Nginx是一款高性能的http服务器/反向代理服务器及电子邮件&#xff08…

Room记录搜索记录逻辑思路

记录数据使用ROOM&#xff0c;传递使用ViewModel LiveDataBus,这篇文章主要记录 搜索记录 本地 线上&#xff0c;上传失败&#xff0c;记录本地&#xff0c;网络回复统一上传等逻辑的操作。 目录 首先是设计数据表&#xff1a; 定义DAO操作接口 定义数据库类 Mvvm 模式中封…

监听其他音频播放时暂停正在播放的音频

要实现当有其他音频播放时暂停当前音频&#xff0c;你可以使用全局事件总线或 Vuex 来管理音频播放状态。这里我将展示如何使用一个简单的事件总线来实现这个功能。 首先&#xff0c;你需要创建一个事件总线。你可以在项目的一个公共文件中创建它&#xff0c;例如 eventBus.js…