【leetcode】动态规划::前缀和

标题:【leetcode】前缀和

@水墨不写bug


正文开始:

(一)简单前缀和

描述

给定一个长度为n的数组a1​,a2​,....an​.

接下来有q次查询, 每次查询有两个参数l, r.

对于每个询问, 请输出al​+al+1​+....+ar​

输入描述:

第一行包含两个整数n和q.

第二行包含n个整数, 表示a1​,a2​,....an​.

接下来q行,每行包含两个整数   l和r.

1≤n,q≤10^5
-10^9≤a[i]≤10^9
1≤l≤r≤n

输出描述:

输出q行,每行代表一次查询的结果.

示例1

输入:

3 2
1 2 4
1 2
2 3

输出:

3
6

         思路一: 暴力求解,时间复杂度O(N^2),看到下方的数据量,显然是会超时的算法;

        思路二:动态规划

        动态规划是一种解决多阶段决策问题的数学优化方法。它将原问题分解为若干个子问题,并把子问题的解保存起来,避免重复计算,从而减少计算量。动态规划通常适用于具有重叠子问题和最优子结构的问题,通过构建一个递推关系式,将问题的最优解表示成子问题的最优解的组合。通过自底向上的方式,从子问题的最优解逐步推导出原问题的最优解。动态规划可以大大提高问题的求解效率,但也需要额外的空间来存储子问题的解。

        通过这一思想,我们可以创建一个dp数组:它的每一个下标i对应的位置存储和它对应下标的arr的前(i)个元素和:

        这时若要求得 [l,r] 闭区间的两个下标之间的元素之和,只需对dp数组操作即可。解题关键就是找到如何构造dp数组的方法,以及如何利用dp数组来得到结果。

        本题构建dp数组的策略比较简单:dp数组的前一项加上arr数组的本项即可得到dp数组的本项:

dp[k] = dp[k-1] + arr[k]

        利用dp数组的方法也很简单:输出dp的r下标和dp的(l - 1)下标之和即可:

cout<<(long)dp[r]-(long)dp[l-1]<<endl;

        时间复杂度O(q);

       

        考虑到题目需要做加法,并且数据量达到10 ^5,数据返回范围达到了10^9量级,所以数据类型开成long

参考代码: 

#include <iostream>
#include <vector>
using namespace std;
int main() {int n,q;cin>>n>>q;vector<long> arr(n+1);for(int i = 1;i < n+1;i++) cin>>arr[i];vector<long> dp(n+1);//构造数组dpfor(int k = 1;k < n+1;k++) dp[k] = dp[k-1] + arr[k];for(int j = 0;j < q;j++)//主逻辑{int l = 0,r = 0;cin>>l>>r;cout<<(long)dp[r]-(long)dp[l-1]<<endl;}
}

(二)二维前缀和

描述

给你一个 n 行 m 列的矩阵 A ,下标从1开始。

接下来有 q 次查询,每次查询输入 4 个参数 x1 , y1 , x2 , y2

请输出以 (x1, y1) 为左上角 , (x2,y2) 为右下角的子矩阵的和,

输入描述:

第一行包含三个整数n,m,q.

接下来n行,每行m个整数,代表矩阵的元素

接下来q行,每行4个整数x1, y1, x2, y2,分别代表这次查询的参数

1≤n,m≤1000
1≤q≤10^5
−109≤a[i][j]≤10^9
1≤x1​≤x2​≤n
1≤y1​≤y2​≤m

输出描述:

输出q行,每行表示查询结果。

示例1

输入:

3 4 3
1 2 3 4
3 2 1 0
1 5 7 8
1 1 2 2
1 1 3 3
1 2 3 4

输出:

8
25
32

备注:

读入数据可能很大,请注意读写时间。

         经过了一维前缀和的铺垫,对前缀和有了一些初步理解,在解决二维前缀和就容易多了:

        题目要求是返回两个坐标之间的元素和:

思路一:暴力求解,时间复杂度O(q*N^2),显然是会超时的算法。

 思路二:用动态规划思想,采用二维前缀和方法。

        首先,我们可以定义一个辅助矩阵dp,其中dp[i][j]表示以(1,1)为左上角,(i,j)为右下角的子矩阵的和。

                                (下标为0的行和列不使用)

        接下来,我们可以通过以下方程来计算dp数组:

dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + A[i][j]

        其中,dp[i-1][j]表示以(1,1)为左上角,(i-1,j)为右下角的子矩阵的和; dp[i][j-1]表示以(1,1)为左上角,(i,j-1)为右下角的子矩阵的和; dp[i-1][j-1]表示以(1,1)为左上角,(i-1,j-1)为右下角的子矩阵的和; A[i][j]表示矩阵A的元素。

        对于每次查询(x1, y1)(x2, y2),我们可以通过如下公式计算子矩阵的和:

sum = dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1]

        其中,dp[x2][y2]表示以(1,1)为左上角,(x2,y2)为右下角的子矩阵的和; dp[x1-1][y2]表示以(1,1)为左上角,(x1-1,y2)为右下角的子矩阵的和; dp[x2][y1-1]表示以(1,1)为左上角,(x2,y1-1)为右下角的子矩阵的和; dp[x1-1][y1-1]表示以(1,1)为左上角,(x1-1,y1-1)为右下角的子矩阵的和。

        其实前缀和是一类题型,我们可以在一定程度上记忆状态转移方程(上述的dp表构建方程,使用dp表方程), 但是我认为更重要的是理解方程为什么是这样的结构,以及方程的推导由来:

         

参考代码: 

#include <iostream>
#include<vector>
using namespace std;int main(){int n = 0,m = 0,q = 0;cin>>n>>m>>q;vector<vector<int>> arr(n+1,vector<int>(m+1));for(int i = 1;i <= n ; i++)//读取数据for(int j = 1;j <= m ; j++)cin>>arr[i][j];vector<vector<long>> dp(n+1,vector<long>(m+1));//long防止溢出for(int i = 1;i <= n ; i++)//建表for(int j = 1;j <= m ; j++)dp[i][j] = dp[i-1][j] + dp[i][j-1] + arr[i][j] - dp[i-1][j-1];for(int c = 0;c<q;c++)//c仅仅起计数作用{int i0 = 0,j0 = 0,i = 0,j = 0;cin>>i0>>j0>>i>>j;long ret = dp[i][j] - dp[i][j0-1] - dp[i0-1][j]+dp[i0-1][j0-1];cout<<ret<<endl;}
}
// 64 位输出请用 printf("%lld")

(三)寻找数组的中心下标

给你一个整数数组 nums ,请计算数组的 中心下标 

数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。

如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。

如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。

示例 1:

输入:nums = [1, 7, 3, 6, 5, 6]
输出:3
解释:
中心下标是 3 。
左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,
右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。

示例 2:

输入:nums = [1, 2, 3]
输出:-1
解释:
数组中不存在满足此条件的中心下标。

示例 3:

输入:nums = [2, 1, -1]
输出:0
解释:
中心下标是 0 。
左侧数之和 sum = 0 ,(下标 0 左侧不存在元素),
右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0 。

提示:

  • 1 <= nums.length <= 10^4
  • -1000 <= nums[i] <= 1000

class Solution {
public:int pivotIndex(vector<int>& nums) {int n = nums.size();vector<long> f(n), g(n);for(int i = 1;i < n;i++)//建f,g表f[i] = f[i-1] + nums[i-1];//不赋值默认为0for(int i = n-2;i >= 0;i--)g[i] = g[i+1] + nums[i+1];for(int k = 0;k < n;k++)if(f[k]==g[k]) return k;return -1;}
};

 (四)除自身外数组的乘积

        给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

        题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在  32 位 整数范围内。

        请 不要使用除法,且在 O(n) 时间复杂度内完成此题。

示例 1:

输入: nums = [1,2,3,4]
输出: [24,12,8,6]

示例 2:

输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

提示:

  • 2 <= nums.length <= 10^5
  • -30 <= nums[i] <= 30
  • 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在  32 位 整数范围内
class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> f(n), g(n);f[0] = g[n-1] = 1;//乘法操作不能初始化为0for(int i = 1;i < n;i++)//建f,g表f[i] = f[i-1] * nums[i-1];//不赋值默认为0for(int i = n-2;i >= 0;i--)g[i] = g[i+1] * nums[i+1];vector<int> ret;for(int i = 0;i < n;i++)ret.push_back(f[i]*g[i]);return ret;}
};

完~

未经作者同意禁止转载

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

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

相关文章

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《考虑灵活爬坡产品的虚拟电厂两阶段分布鲁棒优化运营策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

轨迹规划 | 图解最优控制LQR算法(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 最优控制理论2 线性二次型问题3 LQR的价值迭代推导4 基于差速模型的LQR控制5 仿真实现5.1 ROS C实现5.2 Python实现5.3 Matlab实现 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全…

硬件标准化之道:Linux社区与硬件厂商的协同创新

在Linux的广阔世界中&#x1f30c;&#xff0c;与各式各样的硬件设备进行互动和协作是一项不断进行的挑战&#x1f527;。硬件厂商和Linux社区的紧密合作&#xff0c;通过制定一系列标准和协议&#x1f4dc;&#xff0c;使得从键盘&#x1f3b9;和鼠标&#x1f5b1;到复杂的网络…

七、Ajax(Django开发)

Ajax&#xff08;Django开发&#xff09; 知识点的回顾&#xff1a;1.Ajax请求2.订单小结3.图表4.关于文件上传4.1基本操作案例&#xff1a;批量上传数据案例&#xff1a;混合数据&#xff08;Form&#xff09;4.2启用media案例&#xff1a;混合数据&#xff08;form&#xff0…

C++设计模式:桥模式(五)

1、定义与动机 桥模式定义&#xff1a;将抽象部分&#xff08;业务功能&#xff09;与实现部分&#xff08;平台实现&#xff09;分离&#xff0c;使他们可以独立地变化引入动机&#xff1a; 由于某些类型的固有的实现逻辑&#xff0c;使得它们具有两个变化的维度&#xff0c;…

阿里云服务器可以干嘛 阿里云服务器应用场景有哪些

阿里云服务器可以干嘛&#xff1f;能干啥你还不知道么&#xff01;简单来讲可用来搭建网站、个人博客、企业官网、论坛、电子商务、AI、LLM大语言模型、测试环境等&#xff0c;阿里云百科aliyunbaike.com整理阿里云服务器的用途&#xff1a; 阿里云服务器活动 aliyunbaike.com…

单例模式--理解

单例模式 单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时&#xff0c;为了防止频繁地创建对象使得内存飙升&#xff0c;单例模式可以让程序仅在内存中创建一个对象&#xff0c;让所有需要调用的地方都共享这一单例对象。 单…

使用docker-compose创建多项目容器运行

使用docker-compose创建多项目容器运行 按招网友提供方法创建 docker-compose.yml内容&#xff08;这里改了桥接模式&#xff0c;并且注释放开&#xff09; version: "3" services:docker_python:image: python:2.7.18container_name: py_appworking_dir: "/r…

婴儿洗衣机哪种比较实用?精选四大热门口碑婴儿洗衣机推荐

对于有了宝宝的家庭来说&#xff0c;洗衣成为了一项重要的家务事。大家都知道&#xff0c;宝宝的皮肤比较娇嫩&#xff0c;容易受到各种细菌、病毒的侵扰。所以&#xff0c;宝宝的衣物应该与大人的分开洗。婴儿洗衣机作为一种专门为婴幼儿家庭设计的洗衣机&#xff0c;其具有除…

nginx部署前端教程

目录 一、前言二、部署三、注意四、参考 一、前言 一般来说现在的软件项目&#xff0c;都是分用户端以及管理端的&#xff0c;并且是前后端分离的&#xff0c;这里我来记录一下部署两个前端的教程。 部署前端之前需要的准备工作是部署springBoot后端程序&#xff0c;这里我do…

qt设置异形图片并实现透明效果

思路:将背景设置为透明,然后将图片设置给label,将laben和this都设置为图片大小 setAttribute(Qt::WA_TranslucentBackground, true); 可以将背景设置为透明 然后 QPixmap *pixnew QPixmap(":/Image/xxx.png"); this->setFixedSize(pix->width(),pix->…

对OceanBase中的配置项与系统变量,合法性检查实践

在“OceanBase 配置项&系统变量实现及应用详解”的系列文章中&#xff0c;我们已经对配置项和系统变量的源码进行了解析。当涉及到新增配置项或系统变量时&#xff0c;通常会为其指定一个明确的取值范围或定义一个专门的合法性检查函数。本文将详细阐述在不同情境下&#x…

深入理解指针2:数组名理解、一维数组传参本质、二级指针、指针数组和数组指针、函数中指针变量

目录 1、数组名理解 2、一维数组传参本质 3、二级指针 4、指针数组和数组指针 5、函数指针变量 1、数组名理解 首先来看一段代码&#xff1a; int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf("%d\n", sizeof(arr));return 0; } 输出的结果是&…

[大模型]大语言模型量化方法对比:GPTQ、GGUF、AWQ

在过去的一年里&#xff0c;大型语言模型(llm)有了飞速的发展&#xff0c;在本文中&#xff0c;我们将探讨几种(量化)的方式&#xff0c;除此以外&#xff0c;还会介绍分片及不同的保存和压缩策略。 说明&#xff1a;每次加载LLM示例后&#xff0c;建议清除缓存&#xff0c;以…

python之列表操作

1、创建列表 代码示例&#xff1a; i [1, 2, 34, 4] o list((1, 2, 3, 4, 5, 6)) 分别创建了两个数组&#xff0c;这两种格式都能创建数组 2、关于数组的操作 1、添加元素 1、append&#xff08;&#xff09; append方法主要是添加一个元素 代码示例如下&#xff1a;…

深度学习理论基础(七)Transformer编码器和解码器

学习目录&#xff1a; 深度学习理论基础&#xff08;一&#xff09;Python及Torch基础篇 深度学习理论基础&#xff08;二&#xff09;深度神经网络DNN 深度学习理论基础&#xff08;三&#xff09;封装数据集及手写数字识别 深度学习理论基础&#xff08;四&#xff09;Parse…

手机软件何时统一--桥接模式

1.1 凭什么你的游戏我不能玩 2007年苹果手机尚未出世&#xff0c;机操作系统多种多样&#xff08;黑莓、塞班、Tizen等&#xff09;&#xff0c;互相封闭。而如今&#xff0c;存世的手机操作系统只剩下苹果OS和安卓&#xff0c;鸿蒙正在稳步进场。 1.2 紧耦合的程序演化 手机…

vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户

1.后端返回的json数据结构为&#xff1a; {"message":"下载失败&#xff0c;下载文件不存在&#xff0c;请联系管理员处理&#xff01;","code":500} 2.vue 请求后台接口返回的 Blob数据 3.问题出现的原因是&#xff0c;正常其他数据列表接口&…

[C++][算法基础]堆排序(堆)

输入一个长度为 n 的整数数列&#xff0c;从小到大输出前 m 小的数。 输入格式 第一行包含整数 n 和 m。 第二行包含 n 个整数&#xff0c;表示整数数列。 输出格式 共一行&#xff0c;包含 m 个整数&#xff0c;表示整数数列中前 m 小的数。 数据范围 1≤m≤n≤&#x…

第4章 Redis,一站式高性能存储方案,笔记问题

点赞具体要实现功能有哪些&#xff1f; 可以点赞的地方&#xff1a;对帖子点赞&#xff0c;对评论点赞点一次是点赞&#xff0c;再点一次是取消赞统计点赞的数量&#xff08;计数&#xff0c;string&#xff09;&#xff0c;帖子被点赞的数量&#xff0c;某个用户被点赞的数量…