数组题目总结 -- 前缀和数组

news2024/12/25 1:25:27

目录

  • 一. 区域和检索 - 数组不可变
    • 1. 思路和代码
      • I. 博主的做法:
      • II. 东哥的做法:
    • 2. 总结
  • 二. 二维区域和检索 - 矩阵不可变
    • 1. 思路和代码
      • I. 博主的做法:
      • II. 东哥的做法:
    • 2. 总结

一. 区域和检索 - 数组不可变

  • 题目链接:https://leetcode.cn/problems/range-sum-query-immutable/

1. 思路和代码

I. 博主的做法:

  • 很简单,先在类里面整一个private数组,然后初始化它,只有就是简单的遍历求和。
class NumArray {
    private int[] nummber;
    public NumArray(int[] nums) {
        this.nummber = nums;
    }
    
    public int sumRange(int left, int right) {
        int sum = 0;

        for(int i = left; i <= right; i++)
            sum += nummber[i];

        return sum;
    }
}

II. 东哥的做法:

  • 博主这样写,可以达到效果,但是效率很差,因为 sumRange 方法会被频繁调用,而它的时间复杂度是 O(N),其中 N 代表 nums 数组的长度。
    在这里插入图片描述
  • 构建前缀和数组preSum,这样,sumRange 函数仅仅需要做一次减法运算,避免了每次进行 for 循环调用,最坏时间复杂度为常数 O(1)。
class NumArray {
    private int[] preSum;
    public NumArray(int[] nums) {
        preSum = new int[nums.length + 1];

        for(int i = 1; i < preSum.length; i++)
            preSum[i] = preSum[i-1] + nums[i-1];
    }
    
    public int sumRange(int left, int right) {

        return preSum[right + 1] - preSum[left];

        // return preSum[0];
    }
}
    • 这个技巧在生活中运用也挺广泛的,比方说,你们班上有若干同学,每个同学有一个期末考试的成绩(满分 100 分),那么请你实现一个 API,输入任意一个分数段,返回有多少同学的成绩在这个分数段内。那么,你可以先通过计数排序的方式计算每个分数具体有多少个同学,然后利用前缀和技巧来实现分数段查询的 API:
package LeetCode;

import java.util.*;

/**
 * @Author wangyichao
 * @date 2022/3/22 12:59
 * @Version 1.0
 * @Description
 */
public class Test {
	//前缀和数组	
    private  int[] preCount;
	
    public Test(int[] score){

        preCount = new int[score.length + 1];
		//初始化前缀和数组
        for(int i = 1; i < preCount.length; i++)
            preCount[i] = preCount[i-1] + score[i-1];
    }
    
	//统计分数段[left_core , right_core]中学生的个数
    public int sum(int left_core, int right_core){
        return preCount[right_core + 1] - preCount[left_core];
    }
    
	//使用计数排序(桶排序),统计每一个分数的学生个数
    public static int[] add(int[] score){
        int[] num = new int[100 + 1];

        for(int score1 : score)
            num[score1]++;

        return num;
    }
    
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int left = sc.nextInt();
        int right = sc.nextInt();

        int[] score = add(new int[]{0,1,1,2,3,3,3,4,5});
        Test test = new Test(score);
        
        System.out.println(test.sum(left,right));
    }
}

2. 总结

  • 博主本来想让 preSum[0] 来存储 sum 的值,最后发现结果不对,因为 preSum[0] 这个值也要参与到求和的运算当中。eg:求下标 0 ~ 下标 5 之间元素的和,那么就是 preSum[5 + 1] - preSum[0]。

二. 二维区域和检索 - 矩阵不可变

  • 题目链接:https://leetcode.cn/problems/range-sum-query-2d-immutable/

1. 思路和代码

I. 博主的做法:

  • 博主就是将二维数组的变成很多个一维数组,用多个一维数组构建前缀和数组。
class NumMatrix {
    private int[][] preMatrix;

    public NumMatrix(int[][] matrix) {
    	if(matrix.length == 0 || matrix[0].length == 0)
    		return;
        preMatrix = new int[matrix.length][matrix[0].length + 1];

        for(int i = 0; i < matrix.length; i++){
            for(int j = 1; j < preMatrix[0].length; j++){
                preMatrix[i][j] = preMatrix[i][j-1] + matrix[i][j-1];
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        int sum = 0;

        for(int i = row1; i <= row2; i++)
            sum += preMatrix[i][col2 + 1] - preMatrix[i][col1];

        return sum;
    }
}

II. 东哥的做法:

  • 类似于前缀和的做法, 先算出(0,0,row + 1,col + 1)这个大矩阵的和,也就是下图中绿色方框中的和,然后再减去剩下两个矩形的和,中间有一部分是多减的,现在把它加回来,最后得到了红色矩形的和,也就是我们想得到的结果。
    在这里插入图片描述
  • 我们可以维护一个二维 preMatrix 数组,专门记录以原点为顶点的矩阵的元素之和,就可以用几次加减运算算出任何一个子矩阵的元素和。
  • 这样,sumRegion 函数的时间复杂度也用前缀和技巧优化到了 O(1),这是典型的「空间换时间」思路。
class NumMatrix {
    private int[][] preMatrix;

    public NumMatrix(int[][] matrix) {
        if(matrix.length == 0 || matrix[0].length == 0)
    		return;
        preMatrix = new int[matrix.length + 1][matrix[0].length + 1];

        for(int i = 1; i < preMatrix.length; i++){
            for(int j = 1; j < preMatrix[0].length; j++){
                preMatrix[i][j] = preMatrix[i-1][j] + preMatrix[i][j-1] + matrix[i-1][j-1] - preMatrix[i-1][j-1];
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {


        return preMatrix[row2+1][col2+1] - preMatrix[row1][col2+1] - preMatrix[row2+1][col1] + preMatrix[row1][col1];
    }
}

这里preMatrix的构成还有最后的sumRegion都很迷,博主举个例子帮助大家理解:

score为输入的数组,preMatrix为前缀和数组。
在这里插入图片描述
在这里插入图片描述

  • 以preMatrix当中的14为例:

preMatrix[2][2] = preMatrix[1][2] + preMatrix[2][1] + matrix[1][1] - preMatrix[1][1]
14 (3 + 5 + 6) = 3 (0 + 3) + 8 (3 + 5) + 6 - 3
对应的Matrix如下图:
在这里插入图片描述
在这里插入图片描述

  • 假设要算(1, 1, 2, 2)这个矩阵(黑色方框中矩形)的和:
    在这里插入图片描述

sum = preMatrix[3][3] - preMatrix[1][3] - preMatrix[3][1] + preMatrix[1][1]
11 = 21 (3 + 0 + 1 + 5 + 6 + 3 + 1 + 2 + 0) - 4 (3 + 0 + 1)- 9(3 + 5 + 1) + 3

  • 本质上还是矩阵的相互加减

2. 总结

  • 博主的那个方法,虽然是前缀数组的衍生,但sumRegion时间复杂度为O(n),而东哥的这个时间复杂度为O(1)。
  • 很巧妙,运用迭代的思想构建preMartix数组,又运送矩阵相减的方法,算出sum,东哥牛逼!!!!
    -二维数组.length 返回的是二维数组行的个数,而列的个数要用二维数组[0].length来表示。
  • 一维数组中,只有第一个元素是空的;二维数组中,第一行第一列都是空的。发现一个规律:preMatrix的行数列数都减一就是matrix中对应的矩阵(0, 0, row, col)右下角点的坐标
    • eg:以上面那个例子接着来说,preMatrix[3][3]: (2 ,2)即是大矩阵右下角的坐标,那么整个大矩阵就是(0, 0, 2, 2),也就是下面这个图
      在这里插入图片描述

参考:https://labuladong.github.io/algo/di-yi-zhan-da78c/shou-ba-sh-48c1d/xiao-er-me-03265/

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

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

相关文章

【方法一:二分+字符串哈希 优化】【dp——取不取问题-背包】最长公共子串【上海交通大学考研机试题】

最长公共子串 二分方法字符串哈希的复习字符串哈希 如何理解 二分代码 dp方法字符串str1中以第i个字符为结尾的子串 与字符串str2中以第i个字符为结尾的子串的连续公共子串 二维一维优化 二分方法 由于这个题是要求求子串&#xff0c;而子串是连续的一段&#xff0c;所以用二分…

在微信小程序中怎么使用vant框架?

目录标题 首先介绍什么是vant一、第一步&#xff0c;打开我们小程序项目目录&#xff0c;找到所在的位置&#xff0c;打开终端二、对项目进行初始化三、进行安装依赖1、通过npm安装vant/weapp2、安装miniprogram 四、修改app.json五、修改project.config.json六、然后构建npm 需…

使用Word的一些技巧记录

本文主要用于记录书写毕业论文时&#xff0c;遇到的Word的使用技巧。 设置样式及多级列表 每个学校必然会对论文中的字体、字号、行间距提出要求&#xff0c;设置Word中样式解决此问题。 例如&#xff0c;本校的格式要求为&#xff1a; 正文中的一级标题&#xff08;章目&a…

【C#】GridControl动态更换DataSource,查询数据异常处理

系列文章 【C#】单号生成器&#xff08;编号规则、固定字符、流水号、产生业务单号&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器&#xff08;开始日期、结束日期&#xff09; 本文链接&#xff1a;h…

适应大、中、小型医院的手术麻醉临床信息管理系统源码

手术麻醉管理系统是一款专门用于医院手术麻醉管理的软件系统&#xff0c;它可以帮助医院和医生更好地管理手术麻醉过程&#xff0c;提高手术麻醉的质量和安全性。本文将介绍手术麻醉管理系统的实现、功能概述、主要功能、系统设置、麻醉管理、术中记录、苏醒室记录、PCA实施及管…

【微服务笔记20】微服务组件之Nacos配置中心基础环境搭建、配置持久化、动态刷新配置

这篇文章&#xff0c;主要介绍微服务组件之Nacos配置中心基础环境搭建、配置持久化、动态刷新配置。 目录 一、搭建Nacos配置中心环境 1.1、Nacos配置中心介绍 1.2、搭建Nacos配置中心客户端 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;添加配置信息 &…

图书管理系统的开发与设计(论文+源码)_kaic

摘 要 随着科学技术的快速发展&#xff0c;尤其是计算机技术的突飞猛进&#xff0c;计算机技术普及到日常生活、学习生活的方方面面。由此想到学校的相对于传统的图书管理系统&#xff0c;帮助到学校的读者和学校的图书管理员的系统。提升图书管工作人员的效率&#xff0c;满足…

【C++类和对象】类和对象(中):构造函数 {六个默认成员函数;构造函数的概念及特性;编译器自动生成的构造函数;默认构造函数}

一、类的六个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器…

Pytorch深度学习笔记(六)用pytorch实现线性回归

目录 1.数据准备 2.设计模型 3.构造损失函数和优化器 4.训练周期&#xff08;前馈—>反馈—>更新&#xff09; 课程推荐&#xff1a;05.用PyTorch实现线性回归_哔哩哔哩_bilibili 线性通常是指变量之间保持等比例的关系&#xff0c;从图形上来看&#xff0c;变量之间…

为什么要学习微服务?

文章目录 1.认识微服务1.1微服务由来1.2为什么需要微服务&#xff1f; 2.两种架构2.1.单体架构2.2.分布式架构 3.微服务的特点4.SpringCloud5.总结最后说一句 1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为…

类和对象(上篇)

类和对象----上篇 &#x1f506;面向过程和面向对象的初步认识&#x1f506;类的引入&#x1f506;类的定义&#x1f506;类的访问限定符及封装访问限定符封装 &#x1f506;类的作用域&#x1f506;类的实例化&#x1f506;类的对象大小的计算如何计算一个类的大小结构体内存对…

15天学习MySQL计划(多表联查)第四天

15天学习MySQL计划&#xff08;多表联查&#xff09;第四天 1.多表查询 1.1概述 ​ 指从多张表中查询数据 ​ 在项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互…

【HCIP】Huawei设备下IPV4IPV6共存实验

目录 方法一、普通的GRE将V6基于V4通讯 方法二、6to4的tunnel 方法三、双栈 方法一、普通的GRE将V6基于V4通讯 //方法一和方法二的前提&#xff0c;搭个简单的V4网络就行 [r1]int g0/0/0 [r1-GigabitEthernet0/0/0]ip address 12.1.1.1 24 [r1]router id 1.1.1.1 [r1-Gigabi…

Spring Security 05 密码加密

目录 DelegatingPasswordEncoder 使用 PasswordEncoder 密码加密实战 密码自动升级 实际密码比较是由PasswordEncoder完成的&#xff0c;因此只需要使用PasswordEncoder 不同实现就可以实现不同方式加密。 public interface PasswordEncoder {// 进行明文加密String encod…

如何搭建自己的博客网站(手把手教你搭建免费个人博客网站)

没有前言直接开始正文&#xff0c;搭建一个博客需要服务器&#xff0c;域名&#xff0c;博客程序。 博客程序常用的有wordpress&#xff0c;z-blog&#xff0c;typecho等等&#xff0c;其中wordpress和z-blog最为简单&#xff0c;typecho需要一定的技术含量&#xff0c;这里暂…

使用NPOI做Excel简单报表

文章目录 前言初版表格&#xff0c;单元格的合并进阶表格&#xff0c;单元格美化小结 前言 前面介绍了NPOI单元格样式的使用、单元格合并&#xff0c;以及NPOI提供的颜色。现在用上前面的一些知识点&#xff0c;做一个测试结果表格。 1、 介绍NPOI 的颜色卡、名称以及索引 ht…

图片去摩尔纹简述实现python代码示例

这篇文章主要为大家介绍了图片去摩尔纹简述实现的python代码示例&#xff0c;有需要的朋友可以借鉴参考下&#xff0c;希望能够有所帮助&#xff0c;祝大家多多进步&#xff0c;早日升职加薪 1、前言 当感光元件像素的空间频率与影像中条纹的空间频率接近时&#xff0c;可能产生…

分布式系统需要关注的技术点和面试经常问的点

1、分布式系统概述 关于什么是分布式系统&#xff0c;有很多文章介绍&#xff0c;其实这个并不难理解&#xff0c;大白话讲就是&#xff1a;工厂活多了一个人撑不住&#xff0c;那就多找些工人一起干&#xff0c;要让这么多人为了一个目标干得快干得好&#xff0c;就需要一些规…

自主可控智能网联汽车操作系统

开发自主可控智能网联汽车操作系统的必要性 当下&#xff0c;传统汽车操作系统行业的核心技术几乎由国外的黑莓、谷歌、风河、Vector、ETAS等垄断。操作系统已成为我国智能网联汽车发展过程中的关键卡脖子技术&#xff0c;开发自主可控的智能网联汽车操作系统势在必行。 操作…

CVPR 2023 | 达摩院REALY头部重建榜单冠军模型HRN解读

团队模型、论文、博文、直播合集&#xff0c;点击此处浏览 前言 高保真 3D 头部重建在许多场景中都有广泛的应用&#xff0c;例如 AR/VR、医疗、电影制作等。尽管大量的工作已经使用 LightStage 等专业硬件实现了出色的重建效果&#xff0c;从单一或稀疏视角的单目图像估计高精…