【前缀和】--- 初阶题目赏析

news2024/11/17 21:22:18

 Welcome to 9ilk's Code World

       

(๑•́ ₃ •̀๑) 个人主页:       9ilk

(๑•́ ₃ •̀๑) 文章专栏:    算法Journey  


了解完一维和二维前缀和模板之后,我们来看几道题目感受前缀和的算法原理以及使用场景。


🏠 寻找数组的中心下标

📌 题目解析

寻找数组的中心下标

  • 1 <= nums.length <= 10^4。
  • 如果不存在中心下标则返回-1,有多个中心下标返回最左边的哪个。

📌 算法原理

✏️ 思路一

获取dp前缀和数组,dp[i]用来表示[1,i]区间内数组值之和,由于中心下标是左边区间元素之和 == 右边元素之和,中心坐标不包括在那,所以我们可以先获取前缀和数组,遍历数组,当dp[i-1](左边区间) == dp[n] - dp[i](右边区间),返回中心坐标.

注: 设立变量pos为-1,如果没找到中心下标,直接返回pos.

参考代码 :

class Solution {
public:
    int pivotIndex(vector<int>& nums) 
    {
        //获取前缀和数组
        int n = nums.size();
        vector<int> v(n+1,0);
        vector<int> dp(n+1,0);
        for(int i = 1 ; i <= n ; i++)
        {
             v[i] = nums[i-1];
             dp[i] = dp[i-1] + v[i]; 
        }
        //使用前缀和数组
        int pos = -1;
        for(int i = 1 ; i <= n ; i++)
        {
             if(dp[i-1] == dp[n] - dp[i]) //左 == 右
             {
                pos = i;
                return pos;
             }

        }
       return pos; //没找到中心下标
    }
};

✏️ 思路二

我们的目的是找一个点,它能左右两边区间和相等.由于前缀和算法本质是快速求一段连续区间 的和,本题中右边区间也是一段连续的和,因此我们可以分别求一个前缀和数组f和后缀和数组g来表示左边区间和右边区间。f[i]表示前缀和数组,即【0,i-1】区间数组的和,由此可得f[i] = f[i-1] + nums[i-1] ; g[i]表示后缀和数组,即【i+1,n-1】区间数组的和,由此可以得到g[i] = g[i+1] + nums[i+1].

参考代码 :

class Solution {
public:
    int pivotIndex(vector<int>& nums) 
    {
        int n = nums.size();
        vector<int>  front(n,0); //[0,i-1]
        vector<int> back(n,0);//[i+1 ,n-1]
        //获取前缀和数组
        for(int i = 1; i < n ; i++)
        {
            front[i] = front[i-1] + nums[i-1];
        }
        //获取后缀和数组
        for(int i = n-2 ; i>= 0 ;i--)
        {
             back[i] = back[i+1] + nums[i+1];
        }
        int pos = -1;
        for(int i = 0 ; i < n ; i++)
        {
            if(front[i] == back[i])//前缀 == 后缀
             { 
               pos = i;
               break;
             }
        }
        return pos;
    }
};

注 : 为防止越界,我们将f[0]设置为0,g[n-1]设置为0,因为他们都是边界前面和后面都没有数。

🏠 和为K的子数组

📌 题目解析

和为K的子数组

  • 子数组即数组中非空的连续序列。
  • 1 <= nums.length <= 2 * 10^4
  • -10^7 <= k <= 10^7

📌 算法原理

✏️ 思路一 : 暴力枚举

暴力解法思路很简单,就是两层for循环,记录sum,当sum为k时计数,当本题数组长度较长且数据范围较大,一定是会超时的。

注:本题不能用双指针或滑动窗口做优化,因为left,right的走向不一定是一直同向的,因为数组中可能有0和负数

✏️ 思路二 : 前缀和

1. 当我们遍历到某个位置i时,假设sum[i]为位置i的前缀和([0,i]区间数组和),此时要想求和为k的子数组,就转化成在[0,i]区间内找哪个位置的前缀和正好等于sum[i] - k

2.以i位置为结尾的所有子数组:也就是在遍历数组的过程中,在以i为结尾的区间看是否有哪一段前缀和正好等于sum[i] - k。从整个数组来看,这种做法是囊括所有和为k的子数组的情况的,因为子数组终究是原来整个数组的一部分,我们取以i位置为结尾的子数组观察,这样和为k的部分一直是新数组的右边的部分,不可能在中间部分不用回退了,而且这部分一直不断前进,这就使得当观察某个i位置结尾子数组时,只要它里面有等于k的那段,有几段就能找出几段sum-k。

3.sum[i]的记录:我们没有必要真的去弄一个前缀和数组,只需要一个变量sum来标记前一个位置的前缀和即可。

4. 如何判断以i位置为结尾的子数组内有sum - k:当每次遍历时,每计算一次i位置前缀和,我们就可以放进哈希表计数,这样就能进行计数有几个前缀和等于sum-k。但要注意的是,在计算i位置之前哈希表里面只保存【0,i-1】位置的前缀和。

5. 如果以i位置为结尾的区间正好和为k:此时本身就满足和为k的子数组,我们只需要让hash[0] = 1即可(表示不同位置正好本身为k的情况)。

参考代码:

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) 
    {
         int n = nums.size();
        unordered_map<int,int> ump;
        int sum   = 0;  
        int count = 0;
        ump[0] = 1;
        for(int i = 0 ; i < n;i++)
        {
             sum += nums[i];
             if(ump[sum-k]) count += ump[sum-k] ;//sum-k
             ump[sum]++;//计算完后将sum[i]放进哈希表           
        }
          return count; 
    }
};

🏠 除自身以外数组的乘积

📌 题目解析

除自身以外数组的乘积

📌 算法原理

✏️ 思路一:暴力解法

暴力解法就是固定某个位置将左边乘积算出,再将右边乘积算出即可,但时间复杂度是O(N^2)。

✏️ 思路二:前缀和

跟寻找数组中心下标一样,都要求的是左边右边两段连续区间:

1. 先预处理出前缀积和后缀积区间

f [ i ] = f[ i - 1 ] * nums[ i - 1 ] (前缀积)

g[ i ] = g[i + 1] * nums[ i +1 ] (后缀积)

2.使用两个数组:answer[i] = f[i] * g[i]

3.细节问题:与寻找数组中心下标那道题不同的是,我们这里要求的是积,因此边界都设置为1,这样相当于没乘。(f[0] = 1,g[n-1] = 1)

参考代码:

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) 
    {
        int n = nums.size();
         vector<int> answer(n);
         vector<int> front(n,1);//前缀积数组 [0,i-1]
         vector<int> back(n,1);//后缀积数组  [i+1,n-1] 
         for(int i = 1 ; i < n ;i++)
         {
            front[i] = front[i-1] * nums[i-1];
         }
         for(int i = n-2;i>=0;i--)
         {
             back[i] = back[i+1] * nums[i+1];
         }
         for(int i = 0 ; i < n ; i++)
         {
               answer[i] = front[i] * back[i];
         } 
         return answer;

    }
};

总结:

1. 前缀和是一种思想并不是一定是要求和,本质快速求某一段区间的某个性质。

2.对于前缀和数组边界情况的要灵活处理,同时一段连续区间并不一定就是求前缀,后缀也是一段连续区间。

3. 前缀和算法也可以通过转化问题来解决类似子数组的问题。

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

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

相关文章

多张图片拼接在线制作难吗?学会这招让拼接变得很简单

你是否曾遇到过这样的困境&#xff1f;手机里的照片堆积如山&#xff0c;想要在社交平台上分享&#xff0c;却发现限制多多&#xff0c;根本没办法一次性分享完所有的精彩瞬间。这真是让人既兴奋又苦恼的事情啊&#xff01; 记得上次旅行回来&#xff0c;我拍了一大堆照片&…

精益生产管理咨询师OS:我需要时间!!!

最近一位企业的老板和我聊起管理企业的问题&#xff1a;之前听说精益生产管理不错&#xff0c;就试着在企业推行精益生产管理&#xff0c;结果精益培训搞了一个多月, 课上完了,可总是感觉精益并没有在企业落地,反倒感觉越来越越迷茫了。还抱怨说请精益生产管理咨询师花了很多钱…

AI智能对话绘画二合一系统源码 输入文字就可以快速生成高清图片 带源代码包以及搭建部署教程

系统概述 AI 智能对话绘画二合一系统源码是一款集智能对话与绘画功能于一体的先进系统。它融合了人工智能、计算机视觉等多项技术&#xff0c;能够实现自然语言处理与图像生成的高度协同。 该系统通过对大量文本和图像数据的学习与训练&#xff0c;具备了理解用户意图、生成相…

智游剪辑1.7.0 发布

最近又简单给桌面版升级了一下&#xff0c;一起来看看有啥新功能吧 支持实时输出 之前的文字类功能一般都需要等一会才能给出完整结果&#xff0c;现在它支持实时显示输出结果了&#xff0c;不仅输出更快了&#xff0c;而且还可以实时看到效果 字幕生成功能优化 旧版的字幕生…

vscode开发uniapp项目教程

一&#xff0c;在HB编辑器中用命令行创建uniapp项目&#xff08;vitevue3TS) npx degit dcloudio/uni-preset-vue#vite-ts 项目名称注意&#xff1a;搭梯子在创建或者连手机网络创建&#xff0c;按官方提示的下载模板也行。 在HB编辑器中安装vue3插件 二&#xff0c;在vscod…

抽烟检测算法引领公共场所健康管理的未来抽烟检测算法方案源码

在现代社会&#xff0c;吸烟对公共健康的影响越来越受到关注。为应对这一挑战&#xff0c;智能抽烟检测算法作为一种前沿技术&#xff0c;正逐渐成为公共场所健康管理的得力助手。这些算法通过先进的计算机视觉和深度学习技术&#xff0c;能够实时监控和识别吸烟行为&#xff0…

Linux基础1-基本指令5(more,less,head,tail, | ,find)

本章继续整理其他linux基本指令 一.本章重点 1.more和less命令查看大文本 2.head和tail命令查看小文本和日志 3.使用管道多次处理信息 4.find指令 二.more和less more命令和less命令常用来查看大文本&#xff0c;其中less可以使用上下键快速浏览文本 使用方式 more文件 …

若依ruoyi-vue部署在子域名下(做为子应用)

若依ruoyi-vue部署在子域名下&#xff08;做为子应用&#xff09; 特殊情况需要部署到子路径下&#xff08;做为子应用&#xff09; 文章目录 若依ruoyi-vue部署在子域名下&#xff08;做为子应用&#xff09;一、vue.config.js二、router/index.js三、Navbar.vue四、request.j…

通过查找真实IP bypass WAF

当已知某站存在漏洞时&#xff0c;Web 应用程序防火墙&#xff08;简称WAF&#xff09;是最大的阻碍。通常&#xff0c;这些网站都很老旧&#xff0c;维护得不是很好&#xff0c;因此在大多数情况下&#xff0c;将 WAF 放在它们之上会更容易。有一种方法可以绕过这一层保护&…

【软件文档】软件质量保证计划书(Word完整版)

1 概述 2 质量目标 3 项目基本情况 4 资源 4.1 人员 4.1.1 组织结构 4.1.2 职责 4.2 工具及设施 5 质量保证的主要工作 6 质量保证工作量估算 7 质量保证工作提交的产物 8 变更管理 9 评价标准 10 形成的记录 软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;…

想了解前端开发神器MemFire Cloud,这一文就搞定

在如今这个快速变化的开发世界里&#xff0c;谁不想拥有一款能够极大提升效率的开发神器&#xff1f;如果你也是一个想在开发路上少走弯路的程序员&#xff0c;那你一定要了解一下 MemFire Cloud。这款专为“懒人开发者”准备的全能工具&#xff0c;凭借其便捷的操作和强大的功…

ESP32-C3在MQTT访问时出现“Last error code reported from esp-tls: 0x8001”和问题的分析(5)

接前一篇文章:ESP32-C3在MQTT访问时出现“Last error code reported from esp-tls: 0x8001”和问题的分析(4) 前几篇文章分析了笔者在调试测试MQTT时所遇到的“Last error code reported from esp-tls: 0x8001”的问题。实际上笔者在实际测试时发现,还有另外一种错误情况,…

关于Claude Artifacts的5条总结!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

简道云进销存的设计分析

​简道云-进销存应用是对标标准ERP的核心场景业务流、功能&#xff0c;开发的一款拥有自定义能力的“专业进销存”场景应用产品。 01功能表 简道云-进销存应用&#xff0c;主要是实现进销存业务中的4大工作流程“采购、销售、库存、财务”的场景设计&#xff0c;对应的&#x…

手机删除的照片怎么恢复?被删照片不怕,教你4个恢复秘笈

手机不仅是我们的掌中宝&#xff0c;在手机相册里更是藏着无数秘密与珍贵的回忆。但你是否也遇到过这样的尴尬&#xff1a;一不小心的操作&#xff0c;那些记录生活点滴、定格美好瞬间的照片&#xff0c;就从眼前消失&#xff0c;只留下一串问号和一颗焦急的心。 在数字时代&a…

见合八方发布用于测风雷达的1550nm蝶形MOPA激光器

天津见合八方光电科技有限公司(以下简称“见合八方”)日前发布1550nm蝶形半导体MOPA激光器JMA-BT5515100。 产品介绍 MOPA激光器又称为主振荡功率放大器&#xff0c;MOPA广泛应用于分布式光纤传感、激光雷达等领域&#xff0c;其主体由两部分构成&#xff1a;半导体激光器光放…

尚硅谷大数据技术-Kafka视频教程-笔记01【Kafka 入门】

视频地址&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;从入门到调优&#xff0c;深入全面&#xff09;_哔哩哔哩_bilibili 尚硅谷大数据技术-Kafka视频教程-笔记01【Kafka 入门】尚硅谷大数据技术-Kafka视频教程-笔记02【Kafka 外部系统集成】尚硅谷大数据技术-Kafka视频教程…

VBRAS场景测试方法——如何高效验证网络设备的性能与稳定性

01 vBRAS的产生背景 为了解决传统BRAS中存在的设备资源利用率低、运维复杂和新业务开通缓慢等问题&#xff0c;业界提出了基于转发与 控制分离的vBRAS系统架构。基于转发与控制分离的vBRAS系统架构包括CP和UP两种角色&#xff0c;由二者共同实现BRAS功能。 CP&#xff08;Con…

2024开学季必备好物推荐!这些开学好物不可错过!

随着2024年开学季的到来&#xff0c;无论是重返校园的学生还是刚开学的新朋友&#xff0c;都需要一些实用且高效的工具来助力新学期的学习与生活。为了帮助大家更好地准备&#xff0c;我们精心挑选了一系列开学必备好物。从提升学习效率的学习工具到保证健康生活的日常用品&…

低代码表单 FormCreate 中组件的生成规则详解

在低代码表单组件 FormCreate 中&#xff0c;组件生成规则定义了如何通过 JSON 配置生成表单组件。了解和使用这些规则&#xff0c;您可以灵活地创建和控制各种表单元素。 源码地址: Github | Gitee 数据结构 type Rule {// 生成组件的名称&#xff0c;例如 input, select 等…