我爱学算法之—— 前缀和(中)
一、724. 寻找数组的中心下标
题目解析
这道题,给定数组
nums
,要求我们找出这个数组的中心下标。**中心下标:**指左侧所有元素的和等于右侧所有元素的和。
如果存在多个中心数组下标,就返回最左侧的中心数组下标。
算法思路
暴力解法:
对于这道题,要找出数组的中心下标,暴力解法就是遍历数组,依次判断该位置中心下标(左侧所有元素等于右侧所有元素)。
对于暴力解法,遍历数组nums
;
遍历到i
位置时,判断该位置是否是中心下标,也就是该位置左侧所有元素是否等于右侧所有元素。
优化:
暴力解法要遍历数组,遍历到i
位置时还需求左侧所有元素的和、右侧所有元素的和,就还需再遍历数组来求。
时间复杂度就是O(n)
;对于遍历数组的每一个元素,依次判断该位置是否是中心下标,这里进行不了优化;
那就来看:遍历到i
位置时,求左侧所有元素的和、右侧所有元素的和
在暴力解法中,我们就遍历
i
位置左侧的所有元素,求左侧所有元素的和;遍历i
位置右侧所有元素的和,求右侧所有元素的和。我们可不可以使用更简单的方法来拿到
i
位置所有元素的和?
当然是可以的,我们可以预先处理前缀和与后缀和数组,这样就可以以O(1)
的时间复杂度拿到i
位置左侧所有元素的和、i
位置右侧所有元素的和。
前缀和:
预处理前缀和、后缀和数组:遍历到
i
位置时需要i
位置前面所有元素的和,i
位置后面所有元素的和;这里预先处理前缀和数组f
和后缀和数组g
前缀和数组
f
:f[i]
表示区间[0,i-1]
中所有元素的和。(i
位置前面所有元素的和)后缀和数组
g
:g[i]
表示区间[i+1 , n-1]
中所有元素的和。(i
位置后面所有元素的和)**使用前缀和、后缀和数组:**有了前缀和、后缀和数组,在遍历到
i
位置时只需判断f[i]
是否等于g[i]
即可。如果
f[i] == g[i]
,就表示i
位置是一个中心位置,返回该位置下标i
即可。如果
f[i] != g[i]
,就表示i
位置不是应该中心位置,继续向后遍历即可。预处理前缀和:
这里
f[i]
表示的是[0 , i-1]
中所有元素的和,所以在填表时从1
开始向后填表;f[i] = f[i-1] + nums[i];
g[i]
表示的是[i+1 , n-1]
中所有元素的和,所以在填表时从n-2
开始向前填表;g[i] = g[i+1] + nums[i];
初始化:
- 在填
f[1]
时会用到f[0]
,而f[0]
表示的是[0,-1]
中所有元素的和,该区间不存在。所以初始化f[0] = 0
- 在填
g[n-2]
时会用到g[n-1]
,而g[n-1]
表示[n,n-1]
中所有元素的和,该区间不存在、所以初始化g[n-1] = 0
代码实现
class Solution {
public:int f[10002]; //[0 , i-1]int g[10002]; //[i+1 , n-1]int pivotIndex(vector<int>& nums) {int n = nums.size();f[0] = 0;g[n] = 0;for (int i = 1; i <= n; i++)f[i] = f[i - 1] + nums[i - 1];for (int i = n - 2; i >= 0; i--)g[i] = g[i + 1] + nums[i + 1];for (int i = 0; i < n; i++) {if (f[i] == g[i])return i;}return -1;}
};
二、238. 除自身以外数组的乘积
题目解析
对于这道题,给定一个数组
nums
,要求出数组answer
;其中
anwser[i]
表示nums
数组中除了nums[i]
以外的所有数的乘积。
算法思路
对于这道题,要返回数组answer
,其中answer[i]
表示除了nums[i]
以外的所有数的乘积。
那也就是说,我们需要求出nums
中每一个元素对应的answer[i]
。
暴力解法:
遍历整个数组
nums
,遍历到i
位置时,再遍历整个数组计算除了i
位置之外其他所有数的乘积。
这里时间复杂度就是O(n^2)
。
优化
这里当我们遍历到i
位置时,暴力解法就是再次遍历数组,来计算除了i
以外的所有数的乘积。
也就是以O(n)
的时间复杂度来获取除了i
位置意外所有数的乘积。
这里我们可不可以通过预先处理,来直接就可以拿到除了i
位置意外的所有数的乘积。
这里,当遍历到
i
位置时,我们可以发现i
位置把整个数组分成了两部分:一部分是区间
[0 , i-1]
、另一部分则是区间[i+1 , n-1]
;那我们只要拿到区间
[0 , i-1]
中所有数的乘积,区间[i+1 , n-1]
中所有数的乘积那就可以直接计算除了i
位置以外所有数的乘积。
前缀和(积)
所以,我们就可以通过预先处理前缀积数组,在遍历到i
位置时,就可以以O(1)
的时间复杂度获取到除了i
位置以外的所有数的积。
- 前缀积数组:
f[i]
表示区间[0 , i-1]
中所有数的积- 后缀积数组:
g[i]
表示区间[i+1 , n-1]
中所有数的积预处理前/后缀积数组:
- 前缀积:
f[i] = f[i-1] * nums[i-1]
- 后缀积:
g[i] = g[i+1] * nums[i+1]
使用前/后缀积数组:
在遍历到
i
位置时,除i
位置以外的所有数的乘积sum = f[i] * g[i]
。(这里就可以使用O(1)
的时间复杂度获取除i
位置以外的所有数的乘积)初始化:
- 在预处理前缀积数组时,
f[1]
会用到f[0]
,而区间[0,-1]
显然不存在;为了不影响前缀积数组中的其他数,将f[0]
初始化为1
。- 在预处理后缀积数组时,
g[n-2]
会用到g[n-1]
,而区间[n , n-1]
显然不存在;为了不影响后缀积中的其他数,将g[n-1]
初始化为1
。细节:
- 前缀积:前缀积数组
f[i]
表示区间[0 , i-1]
中所有数的积,在预处理时要处理到n
位置。(从前往后)- 后缀积:后缀积数组
g[i]
表示区间[i+1 , n-1]
中所有数的积,在预处理时就要处理到0
位置。(从后往前)
代码实现
class Solution {
public:int f[100001];int g[100001];vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();f[0] = g[n - 1] = 1;for (int i = 1; i <= n; i++) {f[i] = f[i - 1] * nums[i - 1];}for (int i = n - 2; i >= 0; i--) {g[i] = g[i + 1] * nums[i + 1];}vector<int> ret(n);for (int i = 0; i < n; i++) {ret[i] = f[i] * g[i];}return ret;}
};
三、560. 和为 K 的子数组
题目解析
对于这道题,给定一个数组
nums
和一个整数k
我们要求在
nums
数组中存在多少个和为k
的子数组。注意:这道题中给的的数据范围:
-1000 <= nums[i] <= 1000
算法思路
暴力解法:
首先,对于这道题,暴力解法就是枚举:枚举所有的子数组,然后找出和为k
的子数组的个数。
枚举所有子数组,以
i
为起始位置,j
为结束位置的子数组;求出子数组的和,然后找到子数组和为
k
的个数。
前缀和:
在暴力解法枚举所有子数组中,本质就是先固定i
位置,再枚举以i
位置为起始位置的子数组,寻找和为k
的子数组。
那我们也可以先固定i
位置,再枚举所有以i
位置为结束位置的子数组,然后在这些子数组中,找到和为k
的子数组。
所以,我们在遍历数组时,就可以先固定i
位置,再枚举以i
位置为结束位置的所有子数组,在这些子数组中找和为k
的子数组
那如何去找呢?
在遍历到
i
位置时,我们要找以i
位置为结束位置的所有子数组这和为k
的子数组的个数;那我们就可以将问题转换以下:在区间
[0 , i]
中寻找前缀和为sum - k
的个数。
所以,我们就可以在区间
[0 , i-1]
中找前缀和为sum - k
的个数,找到的就是以i
为结束位置、和为k
的子数组的个数。
所以,现在我们预处理处一个前缀和数组,然后遍历nums
数组,遍历到i
位置时就要在区间[0 , i-1]
中找前缀和等于sum - k
的数量
但是这样来解的话,时间复杂度貌似还不如暴力解法啊,时间复杂度为O(n^2 + n)
啊。
hash
表优化:
我们知道了使用前缀和如何去求以i
位置为结束位置、和为k
的子数组的个数;但是时间复杂度却不如暴力解法。
原因就是:在遍历i
位置时我们还需要去遍历区间[0 , i-1]
中的所有前缀和,才能够知道前缀和为sum - k
的数量。
这里要求前缀和为
sum - k
的数量,就可以使用hash
表来优化:在遍历到
i
位置时,hash
表中存储区间[0 , i-1]
中所有前缀和以及前缀和出现的次数。(这样我们就可以直接获取前缀和为sum - k
的数量。细节问题:
hash
表中存储的是区间[0 , i-1]
中所有的前缀和以及前缀和出现的次数;所以在遍历数组的过程中,依次统计前缀和出现的次数。初始情况下
hash
中一个存在前缀和为0
,出现次数为1
的元素:(0 , 1)
;如果整个数组的和为k
,只有存在(0 , 1)
才能统计上这种情况。使用一个数
sum
来代替整个前缀和数组;这里没有必要去预处理一个前缀和数组,只需用sum
即可代替;
sum
表示遍历到i
位置时,区间[0 , i]
位置的和;这样i
位置之前的前缀和都被统计在hash
表中,而i
位置后面的前缀和不需要。
代码实现
class Solution {
public:int subarraySum(vector<int>& nums, int k) {int n = nums.size();unordered_map<int, int> hash;hash[0] = 1;int sum = 0, ret = 0;for (int i = 0; i < n; i++) {sum += nums[i];if (hash.count(sum - k))ret += hash[sum - k];hash[sum]++;}return ret;}
};
到这里本篇文章内容就结束了,感谢各位的支持
继续加油!!!
相关文章:

我爱学算法之—— 前缀和(中)
一、724. 寻找数组的中心下标 题目解析 这道题,给定数组nums,要求我们找出这个数组的中心下标。 **中心下标:**指左侧所有元素的和等于右侧所有元素的和。 如果存在多个中心数组下标,就返回最左侧的中心数组下标。 算法思路 暴…...
leetcode sql50题
在中文站没找到对应的集合,想来自己动手拷贝过来,方便大家面试复习用,对应英文站点: https://leetcode.com/studyplan/top-sql-50/ Select #1757. 可回收且低脂的产品 链接: https://leetcode.cn/problems/recyclable-and-low-fa…...
word操作(持续更新)
1、图片前面(无间隔格式),有像标题标记一样的黑点 word段落左边的黑色小方块小黑点是什么(段落的换行和分页属性)_哔哩哔哩_bilibili...
AURA智能助手在物联网(IoT)和数字化改造领域的使用
要设计一款在物联网(IoT)和数字化改造领域占据市场主导的AURA智能助手,产品经理需从行业痛点、技术架构、商业模式、生态整合四大维度切入,深度融合工业场景的特殊性。以下是系统性设计框架与落地策略: 一、精准定位:直击工业场景核心痛点 1. 解决企业级关键问题 场景痛…...
怎么把自己电脑设置成服务器?
将自己的电脑设置为服务器可以让您托管网站、文件共享或运行各种服务。以下是设置步骤: 基本设置步骤 选择操作系统: Windows:可使用IIS(Internet Information Services)Linux:常用Apache、Nginx等mac…...

Elasticsearch从安装到实战、kibana安装以及自定义IK分词器/集成整合SpringBoot详细的教程ES(三)
DSL官方地址: DSL查询分类 Elasticsearch提供了基于JSON的DSL(https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl)来定义查询。常见的查询类型包括: 查询所有:查询出所有数据࿰…...
神经网络 隐藏层
神经网络中隐藏层的数量是一个超参数,其选择取决于任务复杂度、数据规模和计算资源。以下是常见的架构类型及其适用场景: 1. 单层隐藏层(浅神经网络) 结构:输入层 → 1 个隐藏层 → 输出层特点: 仅需调整…...

React Hooks 指南:何时使用 useEffect ?
在 React 的函数组件中,useEffect Hook 是一个强大且不可或缺的工具。它允许我们处理副作用 (side effects)——那些在组件渲染之外发生的操作。但是,什么时候才是使用 useEffect 的正确时机呢?让我们深入探讨一下! 什么是副作用…...

API标准的本质与演进:从 REST 架构到 AI 服务集成
在当今数字化浪潮中,API 已成为系统之间沟通与协作的“语言”,REST(Representational State Transfer,表述性状态转移)是一种基于 HTTP 协议的 Web 架构风格。它不仅改变了 Web 应用开发的方式,也成为构建现…...
C++核心编程_继承同名成员处理方式
问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢? 访问子类同名成员 直接访问即可 访问父类同名成员 需要加作用域 class Base { public:Base(){m_A 100;}void func(){cout << "B…...
PHP文件读取漏洞全面剖析:触发点与利用技术
PHP文件读取漏洞全面剖析:触发点与利用技术 引言 PHP作为Web开发中最流行的语言之一,其文件操作功能强大但也暗藏风险。文件读取漏洞是PHP应用中最常见的安全问题之一,攻击者利用这些漏洞可以读取服务器敏感文件,甚至实现远程代…...
解决SQL Server SQL语句性能问题(9)——SQL语句改写(2)
9.4.3. update语句改写 与Oracle类似,SQL Server中,update语句被用户相关技术人员广泛应用于现实日常工作中。但是,有些情况下,尤其是海量数据场景中,update语句也许会带来性能方面的严重问题或极大隐患。因此,为了解决和消除update语句导致的性能问题或隐患,我们将需对…...
学习英语。
1. 先自己翻译一遍(葫芦背书法) 结构 补充修饰 最核心的记忆 然后再修饰 2.意群之间翻译: 1.意群 对于两个意群合起来翻译 方法1就是着重某一 6.或者意群之间 核心词一个介词 于 对于 介词化修饰 3.句子之间关系 主句1 after句子2 那么句…...
2480: 2020年06月2级T1:计算矩阵边缘元素之和
题目描述 2020年06月2级第一题题目:计算矩阵边缘元素之和 输入一个整数矩阵,计算位于矩阵边缘的元素之和。所谓矩阵边缘的元素,就是第一行和最后一行的元素以及第一列和最后一列的元素。 输入 第一行分别为矩阵的行数m和列数n࿰…...

html - <mark>标签
<mark> 标签在HTML中用于高亮显示文本,通常用于突出显示某些重要的部分。它的默认样式通常是背景色为黄色,但你可以通过CSS自定义其外观。 1. 基本用法 <mark> 标签用于标记文本的高亮显示。它常用于搜索结果中,突出显示匹配的…...

JavaWeb:前端工程化-Vue
Vue工程化 介绍 什么是Vue? 小白眼里前端开发 前端工程化 环境准备 D:\Program Files\nodejs Vue项目-快速入门 步骤 D:\front\vue 安装依赖 目录结构 code . vscode打开 启动 VScode侧边栏左下角,没有NPM脚本,如何打开?&…...

AT_abc409_e [ABC409E] Pair Annihilation
AT_abc409_e [ABC409E] Pair Annihilation 赛时没开longlong挂了。 思路 首先我们可以把这棵树转化为一颗有根树,且所有电子的都朝根节点移动。 那么接下来我们就需要选择一个最优的树根。 考虑换根dp。 但是可以发现换根时答案其实是没有变化的。 我们设 f…...
【CSS-6】深入理解CSS复合选择器:提升样式表的精确性与效率
CSS选择器是前端开发的基石,而复合选择器则是其中最强大且实用的工具之一。本文将全面解析CSS复合选择器的类型、用法、优先级规则以及最佳实践,帮助你编写更高效、更精确的样式表。 1. 什么是复合选择器? 复合选择器是通过组合多个简单选择…...
网站静态文件加速-Django项目静态文件存储到腾讯云COS存储提升网络请求速度
解决办法是通过在 Nginx 中把对 /static/ 路径的请求直接指向你的 COS 域名来实现让浏览器直接去拉取 COS 上的静态资源,而不再经过本地服务器。下面给出两种常见的做法,你可以任选其一: 方法一:使用 301/302 Redirect ࿰…...

开疆智能Ethernet/IP转Modbus网关连接西门子BW500积算仪配置案例
本案例是通过Ethernet转Modbus网关将皮带秤数据接入到罗克韦尔1769L32E型PLC中。 首先进行ABB PLC的设置 1, 运行 RSLogix 5000 程序加载Ethernet转Modbus网关的EDS 文件: 2,新建工程并添加PLC 3,New Module添加网关ÿ…...

【五子棋在线对战】三.数据管理模块实现
数据管理模块实现 1.数据库表的设计2.数据管理模块的封装和实现2.1 user_table() && ~user_table()2.2 insert() 注册时新增用户2.3 login() 登录验证,并返回详细的用户信息2.4 通过用户名获取用户信息 && 通过用户id获取用户信息2.5 win() &&a…...

【JMeter】后置处理器 - 提取器
文章目录 概览边界提取器正则提取器JSON提取器 概览 CSS/JQuery提取器;给网页使用JSON提取器:给JSON数据使用★边界提取器:给字符串使用★正则表达式提取器:更加高级的字符使用★Xpath提取器:给网页使用 边界提取器…...
JSON解析崩溃原因及解决方案
问题记录: /************************************************| * 描述: 将ID124执行NFC操作-JSON解析为结构体* 函数名: cJSON_ID124_to_struct* 参数[ I]: *json_string 待解析的指针* 参数[II]: *wireless_rxd 结构体指针* 返回: 成功返回0 失…...

OpenAI技术路线急转:从TypeScript到Rust的Codex CLI重构内幕
目录 前言:OpenAI的技术抉择引发业界思考 Codex CLI:OpenAI的终端AI编程利器 语言抉择的戏剧性反转:从TypeScript到Rust Rust重写的四大技术动因 1. 零依赖部署:消除环境配置痛点 2. 内存安全与沙箱隔离 3. 性能的全面碾压 …...

window下配置ssh免密登录服务器
window下配置ssh免密登录服务器 本地windows远程登录我的ssh服务器10.10.101.xx服务器,想要每次都免密登录这个服务器. 记录下教程,防止后期忘记,指导我实现这个过程。 教程 二、实践步骤:Windows 上配置 SSH 免密登录 2.1 确…...

nginx部署
配置阿里云yum源 安装如下编译工具 yum install -y gcc gcc-c autoconf automake make #安装使用nginx还得安装nginx所需的一些第三方系统库的支持,比如nginx的静态资源压缩功能所需的gzip lib库,nginx需要支持URL重写,所需的pcre库&…...
c语言超详细知识点总结 1500行手写源码 持续更新中ing 从25年5月到6月5日
想象一下,我们身处的数字世界,如同一座座宏伟的建筑。操作系统、编译器、数据库、嵌入式设备乃至绚丽的游戏引擎,它们都是这座大厦的重要组成部分。而C语言,正是构建这一切的坚固基石。自丹尼斯里奇于贝尔实验室孕育出这颗编程界的…...

线性规划饮食问题求解:FastAPI作为服务端+libhv作为客户端实现
之前在 Pyomo介绍-CSDN博客 中介绍过通过Pyomo求解线性规划问题,这里使用FastAPI作为服务端,开源网络库libhv作为客户端,求解饮食成本最小化问题。 服务端测试代码test_fastapi_pyomo_server.py如下: from fastapi import FastAP…...
笔记:算法题目中需要处理 int 某个位的三种方法:for、while、to_string
int n; cin >> n; 1. 使用for观察高位、低位、本位 for(int i 1; i < n; i * 10){ //i 1 当前位为个位, i 10 为十位,以此类推 high n / (i * 10); //这是相对于 i 的高位,例如 i 为个位…...

前端验证下跨域问题(npm验证)
文章目录 一、背景二、效果展示三、代码展示3.1)index.html3.2)package.json3.3) service.js3.4)service2.js 四、使用说明4.1)安装依赖4.2)启动服务器4.3)访问前端页面 五、跨域解决方案说明六…...