C++前缀和算法的应用:使数组相等的最小开销

news2024/11/15 13:30:27

本文涉及的基础知识点

C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频

题目

给你两个下标从 0 开始的数组 nums 和 cost ,分别包含 n 个 正 整数。
你可以执行下面操作 任意 次:
将 nums 中 任意 元素增加或者减小 1 。
对第 i 个元素执行一次操作的开销是 cost[i] 。
请你返回使 nums 中所有元素 相等 的 最少 总开销。
示例 1:
输入:nums = [1,3,5,2], cost = [2,3,1,14]
输出:8
解释:我们可以执行以下操作使所有元素变为 2 :

  • 增加第 0 个元素 1 次,开销为 2 。
  • 减小第 1 个元素 1 次,开销为 3 。
  • 减小第 2 个元素 3 次,开销为 1 + 1 + 1 = 3 。
    总开销为 2 + 3 + 3 = 8 。
    这是最小开销。
    示例 2:
    输入:nums = [2,2,2,2,2], cost = [4,2,8,1,3]
    输出:0
    解释:数组中所有元素已经全部相等,不需要执行额外的操作。
    参数范围
    n == nums.length == cost.length
    1 <= n <= 105
    1 <= nums[i], cost[i] <= 106
    测试用例确保输出不超过 253-1。

分析

原理

假定最后所有数都变成x,那么x的取值范围是[min(nums),max(nums)]。如果x1<nin(nums),那要先变成min(nums),再继续变,显然x1的开销更大。
假定x为x1,开销为ll1,如果x为x1+1,那么开销会如何变化。

如果nums[i]小于x开销增加,比之前多增加1
如果nums[i]等于x开销增加,之前不变,现在加1
如果nums[i]等于x+1开销减少,之前-1,现在不变
如果nums[i]大于x+1开销减少,比之前少1

时间复杂度

分四步,每个时间复杂度都是O(n),故总时间复杂度是O(n)。

步骤

求将各值加1,减少1的消耗,一个值可能有多个,也可能没有
求值小于j的所有数加1或减少1的消耗,也就是前缀和。
所有的数变成0的消耗
枚举x。

代码

核心代码

class Solution {
public:
long long minCost(vector& nums, vector& cost) {
m_c = nums.size();
const int iMaxValue = *std::max_element(nums.begin(), nums.end());
vector vValueConst(iMaxValue+1);//vValueConst[j] 表示将所有nums[i]等于j 加或减1 的消耗
for (int i = 0; i < m_c; i++)
{
vValueConst[nums[i]] += cost[i];
}
vector vSum = { 0 };//vValueConst[j] 表示将所有nums[i]<j 加或减1 的消耗
for (const auto& ll : vValueConst )
{
vSum.emplace_back(ll + vSum.back());
}
long long ll = 0;//记录将所有值变成x 的总消耗
for (int i = 0; i < m_c; i++)
{
ll += abs(nums[i] - 0LL) * cost[i];
}
long long llRet = LLONG_MAX;
for (int x = 0; x < iMaxValue; x++)
{
//[0,x+1) 消耗增加
ll += vSum[x + 1] - vSum[0];
//[x+1,…)
ll -= vSum.back() - vSum[x+1];
llRet = min(llRet, ll);
}
return llRet;
}
int m_c;
};

测试用例

int main()
{
Solution slu;
vector nums, cost;
long long res;
nums = { 1, 3, 5, 2 };
cost = { 2, 3, 1, 14 };
res = slu.minCost(nums,cost);
Assert(8LL ,res);

//CConsole::Out(res);

}

2023年3月旧代码

class Solution {
public:
long long minCost(vector& nums, vector& cost) {
m_c = nums.size();
Init(nums,cost);
return Cost();
}
long long Cost()
{
long long llMin = (1000LL) * 1000 * 1000 * 1000 * 1000 * 1000;
long long llLeftCost = 0, llRightCost = 0;
for (int i = 1; i < m_c; i++)
{
llRightCost += abs((long long)m_vNums[i] - m_vNums[0])*m_vCost[i];
}
llMin = min(llMin, llLeftCost+llRightCost);

	 for (int i = 1; i < m_c; i++)
	 {
		 llLeftCost += m_vSums[i]*(m_vNums[i] - m_vNums[i - 1]);
		 llRightCost -= (m_vSums.back() - m_vSums[i ])*(m_vNums[i] - m_vNums[i - 1]);
		 llMin = min(llMin, llLeftCost + llRightCost);
	 }
	 return llMin;
 }
 void Init(const vector<int>& nums,const vector<int>& cost)
 {
	 std::multimap<int, int> m;
	 for (int i = 0; i < m_c; i++)
	 {
		 m.emplace(nums[i], cost[i]);
	 }
	 for (const auto& it : m)
	 {
		 m_vNums.push_back(it.first);
		 m_vCost.push_back(it.second);
	 }
	 m_vSums.push_back(0);
	 for (const auto& n : m_vCost)
	 {
		 m_vSums.push_back(m_vSums.back() + n);
	 }
 }
 int m_c;
 vector<int> m_vNums, m_vCost;
 vector<long long> m_vSums;

};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

| 充满正能量得对大家说
|
|-|
|闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。|
| 墨家名称的来源:有所得以墨记之。 |
|如果程序是一条龙,那算法就是他的是睛|

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境:

VS2022 C++17

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

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

相关文章

PCL 半径滤波剔除噪点

目录 一、算法原理二、注意事项三、代码实现一、算法原理 PCL半径滤波是删除在输入的点云一定范围内没有达到足够多领域的所有数据点。通俗的讲:就是以一个点p给定一个范围r,领域点要求的个数为m,r若在这个点的r范围内部的个数大于m则保留,小于m则删除。因此,使用该算法时…

arduino抢答器

按键传感器 &#xff1a; 1&#xff0c;如果按键传感器没有按下 他返回的值是1 2&#xff0c;如果按下 返回的值为0逻辑运算符有两种状态 True False 如果返回的是数字 0代表Fales 非0代表True 了解 比较运算和逻辑运算 如果两个传感器同时按下两个小灯才会亮 只要其中一…

【Android知识笔记】热修复专题

Android类加载与双亲委派知识回顾 Android 中的 ClassLoader 继承关系: 双亲委派模型: 在 Android 系统中,应用程序中默认的 ClassLoader 是 PathClassLoader 对象,即通过Context.getClassLoader()获取到的是一个 PathClassLoader 对象,而 PathClassLoader 对象的parent是…

[AUTOSAR][诊断管理][ECU][$22] 读取相关的数据

文章目录 一、简介$22服务的实际用途是什么?$22服务的应用场景有哪些呢?$22服务的诊断格式如何?常见DID总结请求实例服务响应负响应NRCNRC优先级二、示例代码uds22_read_data_by_ld.c一、简介 22服务作为诊断服务种的基础服务,可以简单理解为就是一个用于读取ECU数据的外部…

Redis(05)| 数据结构-哈希表

哈希表是一种保存键值对&#xff08;key-value&#xff09;的数据结构。 哈希表中的每一个 key 都是独一无二的&#xff0c;程序可以根据 key 查找到与之关联的 value&#xff0c;或者通过 key 来更新 value&#xff0c;又或者根据 key 来删除整个 key-value等等。 在讲压缩列表…

【torch高级】一种新型的概率学语言pyro(01/2)

一、说明 贝叶斯推理&#xff0c;也就是变分概率模型估计&#xff0c;属于高级概率学模型&#xff0c;极有学习价值&#xff1b;一般来说&#xff0c;配合实际活动学习可能更直观&#xff0c;而pyro是pytorch的概率工具&#xff0c;不同于以往的概率工具&#xff0c;只是集中于…

【咕咕送书 | 第四期】《ChatGPT 驱动软件开发:AI 在软件研发全流程中的革新与实践》

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《粉丝福利》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 ⛳️ 写在前面参与规则一、前言1.0 人工智能新技术如何创新工作 &#xff1f; 二、内容简介三、作者简介四、专家推…

Makefile三个版本的编写

1.Makefile Makefile是一个工程管理文件&#xff0c;简化编译的流程&#xff0c;完成自动化编译的过程 在Makefile中&#xff0c;会把编译的过程分为两步&#xff0c;先生成.o文件&#xff0c;再对.o文件链接&#xff0c;生成可执行文件 Makefile由变量、函数、和规则构成 2.引…

Linux 系统调用IO口,利用光标偏移实现文件复制

用系统调用IO函数实现从一个文件读取最后2KB数据并复制到另一个文件中&#xff0c;源文件以只读方式打开&#xff0c;目标文件以只写的方式打开&#xff0c;若目标文件不存在&#xff0c;可以创建并设置初始值为0664&#xff0c;写出相应代码&#xff0c;要对出错情况有一定的处…

从入门到精通Ansible Playbook,一篇就够了

Playbook 一、Host Inventory(主机清单)1.1 简介1.2 inventory 文件1.2 inventory 中的变量 二、Playbook 剧本2.1 简介2.2 Playbook的组成部分2.3 如何编写Playbook&#xff1f;2.3.1 基本格式2.3.2 语句的横向/纵向写法 三、Playbook实例和知识点补充3.1 编写yum安装nginx的p…

si24r1/nrf24l01

Si24R1 可配置为 Shutdown、 Standby、 Idle-TX、 TX 和 RX 五种工作模式。 芯片上电后为shutdown模式。此模式下不可以通过芯片收发数据&#xff0c;但MCU和芯片可以通过spi协议通信&#xff0c;更改内部寄存器的状态&#xff08;如设置 CONFIG 寄存器下的 PWR_UP 位的值为 1&…

Java练习题2020 -1

统计1到N的整数中&#xff0c;被A除余A-1的偶数的个数 输入说明&#xff1a;整数 N(N<10000), A, (A 输出说明&#xff1a;符合条件的数的个数 输入样例&#xff1a;10 3 输出样例&#xff1a;2 (说明&#xff1a;样例中符合条件的2个数是 2、8) import java.util.Scanner;p…

Java SE 学习笔记(十四)—— IO流(3)

目录 1 缓冲流1.1 缓冲流概述1.2 字节缓冲流1.3 字符缓冲流 2 转换流2.1 字符输入转换流2.1 字符输出转换流 3 序列化3.1 对象序列化3.2 对象反序列化 4 打印流5 与Properties结合使用6 IO 框架 1 缓冲流 1.1 缓冲流概述 我们之前学习的字节流、字符流属于基础流、原始流&…

引流大法,助你销量翻倍!亚马逊新卖家必备的六种流量来源!

作为亚马逊的一个新卖家&#xff0c;我们在新店上传产品之后&#xff0c;第一个目标就是引流&#xff0c;因为流量是支撑店铺销量的重要环节&#xff0c;那么我们引流的方式都有哪些呢&#xff1f; ​首先我们要知道亚马逊的一些流量来源分别有哪几块&#xff01; 一、平台自…

计算机网络重点概念整理-第五章 传输层【期末复习|考研复习】

第五章 传输层 【期末复习|考研复习】 计算机网络系列文章传送门&#xff1a; 第一章 计算机网络概述 第二章 物理层 第三章 数据链路层 第四章 网络层 第五章 传输层 第六章 应用层 第七章 网络安全 计算机网络整理-简称&缩写 文章目录 第五章 传输层 【期末复习|考研复习…

通过宏定义解决编程难题

大家好&#xff0c;我们今天来通过我们的define定义宏解决C语言上的难题。 实例一&#xff1a; offsetof这个宏我们在学习结构体的时候就已经了解过了&#xff0c;这个宏是我们在计算结构体大小的时候来查看每个结构体成员的偏移量的&#xff0c;那么我们在这里就来模拟实现一…

【LeetCode:2558. 从数量最多的堆取走礼物 | 大根堆】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

面试算法43:在完全二叉树中添加节点

题目 在完全二叉树中&#xff0c;除最后一层之外其他层的节点都是满的&#xff08;第n层有2n-1个节点&#xff09;。最后一层的节点可能不满&#xff0c;该层所有的节点尽可能向左边靠拢。例如&#xff0c;图7.3中的4棵二叉树均为完全二叉树。实现数据结构CBTInserter有如下3种…

线程状态,BLOCKED和WAITING 有什么区别

BLOCKED 和 WAITING 都是属于线程的阻塞等待状态。 BLOCKED BLOCKED 状态是指线程在等待监视器锁的时候的阻塞状态。 也就是在多个线程去竞争 Synchronized 同步锁的时候&#xff0c;没有竞争到锁资源的 线程&#xff0c;会被阻塞等待&#xff0c;这个时候线程状态就是 BLOCK…

众和策略:数据要素市场腾飞在即 游戏市场持续高增长

昨日&#xff0c;两市股指早盘弱势下探&#xff0c;午后沪指在银行、电力等板块的带动下发力拉升&#xff0c;深成指、创业板指均走高。到收盘&#xff0c;沪指涨0.48%报2988.3点&#xff0c;深成指涨0.4%报9566.1点&#xff0c;创业板指涨0.65%报1875.86点&#xff1b;两市合计…