[LC 总结] 前缀和(Prefix Sum)总结 10 道相关练习题

news2024/12/23 9:47:40

[LC 总结] 前缀和(Prefix Sum)总结& 10 道相关练习题

类型与题目列表如下:

在这里插入图片描述

题目的解法都做过了,会留在最后一个部分,接下来就梳理一下 prefix sum,列举的题目从简单到 -> 困难

基础

prefix sum 其本身是一个数组相关的数据类型,它的实现方法也非常的简单,以存在数组 nums 为例,就是使用另外一个数组,保存 ∑ k = i i n u m s [ k ] \sum_{k=i}^{i} nums[k] k=iinums[k] 的值,以 [1, 2, 3, 4, 5] 为例,对应的 prefix sum 为 [1, 3, 6, 10, 15][0, 1, 3, 6, 10, 15]

prefix sum 的走向为 0 -> len(nums),如果是走向为 len(nums) -> 0,那么这个被称之为 suffix sum,或是 postfix sum,以 [1, 2, 3, 4, 5] 来说,它所对应的 suffix sum 为 [15, 14, 12, 9, 5][15, 14, 12, 9, 5, 0]

prefix sum(包含 suffix sum)的优点在于,在已经构筑 prefix sum 后,寻找任意下标所耗费的时间为 O ( 1 ) O(1) O(1)。换言之,如果给定任意 i i i,寻找 i + k i + k i+k 的子数组之和只需要花费 O ( 1 ) O(1) O(1) 的时间,其实现方法为 p r e f i x _ s u m [ i + k ] − p r e f i x _ s u m [ i − 1 ] prefix\_sum[i + k] - prefix\_sum[i - 1] prefix_sum[i+k]prefix_sum[i1],如:

在这里插入图片描述

也因为这个特性,prefix sum 又可以被使用 hash map 的结构去实现。

除此之外,对 prefix array 进行其他的操作——如求平均值、最大、最小——均可以被视作 prefix sum 的变种题

prefix

仅用 prefix 一个技巧的题目有点少,1343 是一个案例:

Given an array of integers arr and two integers k and threshold, return the number of sub-arrays of size k and average greater than or equal to threshold.

这个题目的 prefix sum 解法可以用 p r e f i x _ s u m [ i + k ] − p r e f i x _ s u m [ i − 1 ] prefix\_sum[i + k] - prefix\_sum[i - 1] prefix_sum[i+k]prefix_sum[i1] 去找到长度为 k 的子数组之和,随后看看是不是满足条件(平均数 >= threshold)即可

对比仅用单一的 prefix sum 技巧的话,其实 sliding window 更方便一些……毕竟长度是固定的

prefix + suffix

这里面我做过的有 2909,2874,238 和 2102,题目分别如下:

2874:

You are given a 0-indexed integer array nums.

Return the maximum value over all triplets of indices (i, j, k) such that i < j < k. If all such triplets have a negative value, return 0.

The value of a triplet of indices (i, j, k) is equal to (nums[i] - nums[j]) * nums[k].


2909:

You are given a 0-indexed array nums of integers.

A triplet of indices (i, j, k) is a mountain if:

  • i < j < k
  • nums[i] < nums[j] and nums[k] < nums[j]

Return the minimum possible sum of a mountain triplet of nums. If no such triplet exists, return -1.


238:

Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].

The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

You must write an algorithm that runs in O(n) time and without using the division operation.


2012:

You are given a 0-indexed integer array nums. For each index i (1 <= i <= nums.length - 2) the beauty of nums[i] equals:

  • 2, if nums[j] < nums[i] < nums[k], for all 0 <= j < i and for all i < k <= nums.length - 1.
  • 1, if nums[i - 1] < nums[i] < nums[i + 1], and the previous condition is not satisfied.
  • 0, if none of the previous conditions holds.
    Return the sum of beauty of all nums[i] where 1 <= i <= nums.length - 2.

其题型的主要特点就是:

  • 是一个数组
  • 数组可以分为 [ 0 , 1 , . . . , i ] [0, 1, ..., i] [0,1,...,i] [ i , i + 1 , . . . , l e n ( a r r ) ) [i, i+1, ..., len(arr)) [i,i+1,...,len(arr)) 两段去处理
  • 对所有 i i i 而言, [ 0 , 1 , . . . , i ] [0, 1, ..., i] [0,1,...,i] [ i , i + 1 , . . . , l e n ( a r r ) ) [i, i+1, ..., len(arr)) [i,i+1,...,len(arr)) 的处理方式都是一样的

这里对这四道题来说也是一样的:

  • 2874 是对 [ 0 , 1 , . . . , i ] [0, 1, ..., i] [0,1,...,i] [ i , i + 1 , . . . , l e n ( a r r ) ) [i, i+1, ..., len(arr)) [i,i+1,...,len(arr)) 求 max
  • 2909 是对 [ 0 , 1 , . . . , i ] [0, 1, ..., i] [0,1,...,i] [ i , i + 1 , . . . , l e n ( a r r ) ) [i, i+1, ..., len(arr)) [i,i+1,...,len(arr)) 求 min
  • 238 求的是 product sum
  • 2012 则是对 [ 0 , 1 , . . . , i ] [0, 1, ..., i] [0,1,...,i] 求 max,对 [ i , i + 1 , . . . , l e n ( a r r ) ) [i, i+1, ..., len(arr)) [i,i+1,...,len(arr)) 求 min

也就是说,处理这类题型的方式可以使用 prefix array 去存储 0 -> len(nums) 的处理结果,用 suffix array(可以简化成只用一个变量) 去存储 len(nums) -> 0 的处理结果,最后筛选出满足题意的结果

hashtable + prefix sum

这种类型的基础题为 560. Subarray Sum Equals K,这道题可以说是后面很多题的一个基础,其运用的技巧就在上面提到过的:如果给定任意 i i i,寻找 i + k i + k i+k 的子数组之和只需要花费 O ( 1 ) O(1) O(1) 的时间,其实现方法为 p r e f i x _ s u m [ i + k ] − p r e f i x _ s u m [ i − 1 ] prefix\_sum[i + k] - prefix\_sum[i - 1] prefix_sum[i+k]prefix_sum[i1] 这一特性

之所以使用哈希表而不是数组,则是因为哈希表中保存的为 {前缀和: 前缀和出现的次数} 这一搭配,用以比较方便的寻找满足和为 k 的组合

以 560 为例,它求的是子数组之和为 k 的排列组合,这里可以将 k 视作 p r e f i x _ s u m [ i + k ] − p r e f i x _ s u m [ i − 1 ] prefix\_sum[i + k] - prefix\_sum[i - 1] prefix_sum[i+k]prefix_sum[i1] 的结果,哈希表中又保存的是 {前缀和: 前缀和出现的次数},因此只要通过使用 当前前缀和 - k 就能够获取 p r e f i x _ s u m [ i − 1 ] prefix\_sum[i - 1] prefix_sum[i1] 出现的次数,如:

在这里插入图片描述

进阶篇

这里就是几种技巧的组合了

prefix + 2 pointers

这个在做过的题里面有两个:1343 Number of Sub-arrays of Size K and Average Greater than or Equal to Threshold 和 1248 Count Number of Nice Subarrays,题目分别如下:

1248:

Given an array of integers nums and an integer k. A continuous subarray is called nice if there are k odd numbers on it.

Return the number of nice sub-arrays.

这两道题用双指针的解法比较直接,不过使用 hashtable 也可以,不过这里存的不是频率,而是 i i i 之前出现了多少个字符(不同的组合)

这道题我刚开始用的是双指针,不过后面看了下 prefix sum,写法比双指针简单

hashtable + prefix sum 变种

这里我做过的题目典型是 974,这里哈希表中保存的不是 prefix sum,而是 p r e f i x _ s u m % k prefix\_sum \% k prefix_sum%k,这样就能满足题目中 Subarray Sums Divisible by K 这一需求

原理就是,如果找到余数相同的子数组,自然也就意味着找到可以满足被 k 整除的子数组这一条件

hashtable + prefix + BST

这个体形本质上就是更多技巧的累积,相比较而言 BST 有些边界条件需要处理,总体上知道思路也能写出来(medium 范畴),题目为 437 Path Sum III

prefix + suffix + monotonic stack

这道题之前周赛出现的 2866 Beautiful Towers II,它的前置要求为能解 84 Largest Rectangle in Histogram,会 84 Largest Rectangle in Histogram 就是花时间磨一下 84 的题解套用 prefix+suffix 的技巧

简单的说一下就是从 [ 0 , 1 , . . . , i ] [0, 1, ..., i] [0,1,...,i] [ i , i + 1 , . . . , l e n ( a r r ) ) [i, i+1, ..., len(arr)) [i,i+1,...,len(arr)) 分别找到最大的面积,然后二者相加即可。不过这找最大面积的技巧有些的麻烦,需要使用单调栈。如果不了解单调栈的话,这道题估计挠破脑袋都很难想到答案……

不过这道题能被归类成 medium 我是真的没想到就是了

写过的题解

  • 1343 Number of Sub-arrays of Size K and Average Greater than or Equal to Threshold
  • 2874. Maximum Value of an Ordered Triplet II & 2909. Minimum Sum of Mountain Triplets II
  • 238 Product of Array Except Self & 2012. Sum of Beauty in the Array
  • 哈希表 - 和为 K 的子数组, leetcode 560
  • 1248 Count Number of Nice Subarrays
  • 974 Subarray Sums Divisible by K
  • 437 Path Sum III
  • 2866 Beautiful Towers II
    • [python 刷题] 84 Largest Rectangle in Histogram

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

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

相关文章

【深蓝学院】手写VIO第9章--课程总结--笔记

0. 内容 1. 课程回顾 最大后验概率MAP&#xff0c;如果不知道先验则是MLE&#xff0c;如果观测服从高斯分布&#xff08;关于为什么服从高斯分布有个pdf&#xff09;则可转化为LSP。 残差构建主要讲了IMU残差的构建&#xff0c;包括预积分模型&#xff0c;误差模型&#xff08;…

使用Android Jetpack Compose渲染效果打造酷炫的动画效果

如何在Android Jetpack Compose中使用渲染效果打造令人惊艳的视觉体验 学习示例&#xff1a;如何使用渲染效果来改变UI界面 引言 Jetpack Compose提供了各种工具和组件来构建引人入胜的UI&#xff0c;而在Compose中较为鲜为人知的一个宝藏是RenderEffect。 在这篇博文中&a…

freertos任务参数

实现多个任务利用同一个函数&#xff0c;传进不同的任务参数&#xff0c;打印不同的任务内容。多个人用同一个电脑干不同工作&#xff0c;美工用电脑干美工&#xff0c;程序员用电脑敲代码 #include "stm32f10x.h" // Device header #include &quo…

.NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth

前言 我相信做开发的同学应该都对接过各种各样的第三方平台的登录授权&#xff0c;来获取用户信息&#xff08;如&#xff1a;微信登录、支付宝登录、QQ登录、GitHub登录等等&#xff09;。今天给大家推荐一个.NET开源好用的、全面的、方便第三方登录组件集合框架&#xff1a;…

【ES专题】ElasticSearch功能详解与原理剖析

目录 前言要点阅读对象阅读导航前置知识笔记正文一、ES数据预处理1.1 Ingest Node&#xff1a;摄入节点1.2 Ingest Pipeline&#xff1a;摄入管道1.3 Processor&#xff1a;预处理器——简单加工1.4 Painless Script&#xff1a;脚本——复杂加工1.5 简单实用案例 二、文档/数据…

C语言——从键盘任意输人一个三位数的自然数,求该数个位、十位、百位上的数字之和

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int i,ge,shi,bai;printf("输入一个三位数整数&#xff1a;\n");scanf("%d",&i);gei%10; //个位shii%100/10; //十位baii/100; //百位printf("个位:%d,十位:%d,百位:…

51基于matlab模拟退火算法矩形排样

基于matlab模拟退火算法矩形排样&#xff0c;基于最低水平线算法完成矩形板材下料优化&#xff0c;输出最优剩料率和最后的水平线&#xff0c;可替换自己的数据进行优化&#xff0c;程序已调通&#xff0c;可直接运行。 51matlab模拟退火算法矩形排样 (xiaohongshu.com)

两个栈实现队列

要用两个栈实现队列&#xff0c;就需要了解栈和队列的特性&#xff0c;栈是先进后出&#xff0c;队列是先进先出。基本思路是&#xff0c;把数据先压入栈1中&#xff0c;然后数据在栈1中输出再压入栈2&#xff0c;输出后就能实现队列的先进先出。 package Package;import java.…

实施数字工厂管理系统对印刷企业来说有什么意义

随着科技的飞速发展&#xff0c;数字化转型已成为各行各业不可避免的趋势。对于印刷企业而言&#xff0c;实施数字工厂管理系统不仅意味着技术的升级&#xff0c;更关乎企业整体的运营效率、成本控制、市场竞争力等方面的提升。本文将详细分析实施数字工厂管理系统对印刷企业的…

Redis7--基础篇2(Redis的十大数据类型及常用命令)

1. Redis的十大数据类型及常用命令 Redis是key-value键值对类型的数据库&#xff0c;我们所说的数据类型指的是value的数据类型&#xff0c;key的数据类型都是字符串。 1.1 字符串&#xff08;String&#xff09; string是redis最基本的类型&#xff0c;一个key对应一个val…

Docker 学习路线 10:容器安全

容器安全是实施和管理像Docker这样的容器技术的关键方面。它包括一组实践、工具和技术&#xff0c;旨在保护容器化应用程序及其运行的基础架构。在本节中&#xff0c;我们将讨论一些关键的容器安全考虑因素、最佳实践和建议。 容器隔离 隔离对于确保容器化环境的强大性和安全…

CSDN每日一题学习训练——Java版(对给定的两个日期之间的日期进行遍历、子集 II、填充每个节点的下一个右侧节点指针)

版本说明 当前版本号[20231107]。 版本修改说明20231107初版 目录 文章目录 版本说明目录对给定的两个日期之间的日期进行遍历题目解题思路代码思路参考代码 子集 II题目解题思路代码思路参考代码 填充每个节点的下一个右侧节点指针题目解题思路代码思路参考代码 对给定的两…

【计算机组成】实模式/保护模式下地址分段(基段地址+偏移地址)的原因

一.硬编码/静态重定向 我们先来观察下没有地址分段时代CPU是怎么和内存们打交道&#xff0c;在8086CPU以前的老大哥们&#xff0c;访问内存时通常就是实打实的“指哪打哪”&#xff0c;程序指定要放在哪个地址&#xff0c;那就老老实实地放在哪个地址&#xff0c;比如程序A要放…

如何使新手小白编码能力暴涨之Devchat-AI

在这个快速发展的时代&#xff0c;开发者的任务越来越繁重&#xff0c;要求他们快速、高效地完成开发任务。然而&#xff0c;传统的开发方式已经无法满足这个需求。在这种情况下&#xff0c;Devchat的出现给开发者带来了新的帮助。Devchat是一个研发效能分析平台&#xff0c;它…

掌握未来技术趋势:深度学习与量子计算的融合

掌握未来技术趋势&#xff1a;深度学习与量子计算的融合 摘要&#xff1a;本博客将探讨深度学习与量子计算融合的未来趋势&#xff0c;分析这两大技术领域结合带来的潜力和挑战。通过具体案例和技术细节&#xff0c;我们将一睹这两大技术在人工智能、药物研发和金融科技等领域…

【Node.js入门之—1.1Node.js 简介】

Node.js入门之—1.1Node.js 简介 文章目录 Node.js入门之—1.1Node.js 简介什么是 Node.js错误说法 Node.js 的特点跨平台三方类库自带http服务器非阻塞I/O事件驱动单线程 Node.js 的应用场合适合用Node.js的场合不适合用Node.js的场合弥补Node.js不足的解决方案 什么是 Node.j…

Oracle RAC是啥?

Oracle RAC&#xff0c;全称是Oracle Real Application Cluster&#xff0c;翻译过来为Oracle真正的应用集群&#xff0c;它是Oracle提供的一个并行集群系统&#xff0c;由 Oracle Clusterware&#xff08;集群就绪软件&#xff09; 和 Real Application Cluster&#xff08;RA…

Linux之如何使用git提交代码到gitee上

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、创建gitee仓库1、进入gitee2、注册账号3、创建仓库 二、使用Linux创建1、打开Xshell创建一…

SpringBoot工程四种创建方式

创建SpringBoot项目时选择依赖&#xff1a;Spring Web、MySQL Driver、Thymeleaf、lombok 开发控制器类&#xff1a;标记了Controller的类就是一个handler类 handler类在SpringBoot中的作用就是&#xff1a;其内部的方法可以接受请求&#xff0c;处理请求&#xff0c;返回响应…

Intel oneAPI笔记(4)--jupyter官方文档(Unified Shared Memory)学习笔记

前言 本文是对jupyterlab中oneAPI_Essentials/03_Unified_Shared_Memory文档的学习记录&#xff0c;主要包含对统一共享内存的讲解 USM概述 USM (Unified Shared Memory)是SYCL中基于指针的内存管理。对于使用malloc或new来分配数据的C和C程序员来说应该很熟悉。当将现有的C…