当前位置: 首页 > news >正文

LeetCode 每日一题 1526. 形成目标数组的子数组最少增加次数

1526. 形成目标数组的子数组最少增加次数

给定一个整数数组 target 和一个初始全为 0 的数组 initial,要求通过最少的操作次数将 initial 变为 target。每次操作可以选择任意子数组,并将子数组中的每个元素增加 1

示例分析
  • 示例 1

    • 输入:target = [1,2,3,2,1]
    • 输出:3
    • 解释:通过 3 次操作从 [0,0,0,0,0] 变为 [1,2,3,2,1]
  • 示例 2

    • 输入:target = [3,1,1,2]
    • 输出:4
    • 解释:通过 4 次操作从 [0,0,0,0] 变为 [3,1,1,2]
  • 示例 3

    • 输入:target = [3,1,5,4,2]
    • 输出:7
    • 解释:通过 7 次操作从 [0,0,0,0,0] 变为 [3,1,5,4,2]
  • 示例 4

    • 输入:target = [1,1,1,1]
    • 输出:1
    • 解释:通过 1 次操作从 [0,0,0,0] 变为 [1,1,1,1]

题解

方法一:模拟(会超时)

从 0 开始构造 target 数组相当于将 target 数数组变为全 0
每次操作可以选择一段区间 [l,r] 进行 -1 ,直到变为全 0
对一段区间进行 -1 操作,可以使用差分数组快速实现

由于需要减去的总数字大小是固定,即target数据总和,为了得到最少操作数,每一次的操作区间自然是越大越好

但是由于操作过程中会出现 0 ,0-1=-1 不能全数据变为 0,所以区间内是不能包含 0 的,即操作区间会被 0 分割

对于数组内连续且相同的数据,操作区间只要包含其中一个数据,那么剩余的连续且相同的数据都可以一起包含进去,所以相当于只是一个数据,可以化简 target 数组

于是模拟每一次操作,每次操作的区间为子数组被 0 分割的部分,直到数组内所有数字都是 0 即可

对于区间内操作,利用差分数组实现

由于每一次模拟操作都需要遍历数组找到被 0 分割的区间,所以时间复杂度是 n^2


代码如下↓

class Solution {
public:int minNumberOperations(vector<int>& target) {int res = 0;int n = target.size();vector<int> target_simple;  // 存储化简后的差分数组int back = 0;// 化简数组:合并连续相同值(因相同值可被同一操作覆盖)for (int i = 0; i < n; i++) {if (i && target[i] == back) continue;  // 跳过连续相同值target_simple.push_back(target[i] - back); // 计算差分值back = target[i];}n = target_simple.size();int f = 1;  // 循环标志:数组中是否仍有非零元素while (f) {int sum = 0;      // 当前累积和(用于定位0分割点)int l = 0;        // 当前区间左边界int min_v = 0x3f3f3f3f;  // 当前区间内最小值for (int i = 0; i < n; i++) {sum += target_simple[i];  // 更新累积和// 当累积和归零时,说明遇到分割点if (!sum) {if (min_v == 0x3f3f3f3f) min_v = 0;  // 处理空区间res += min_v;  // 累加操作次数// 更新差分数组:区间左减右加target_simple[l] -= min_v;target_simple[i] += min_v;l = i + 1;     // 移动左边界min_v = 0x3f3f3f3f;  // 重置最小值} else {min_v = min(sum, min_v);  // 更新区间最小值}}// 处理末尾未闭合区间if (l < n) {res += min_v;target_simple[l] -= min_v;}// 检查数组是否全零f = 0;sum = 0;for (int i = 0; i < n; i++) {sum += target_simple[i];if (sum) {f = 1;  // 存在非零元素则继续循环break;}}}return res;}
};

方法二:差分思想

可以利用差分数组进行理解

对原数组区间进行 -1,即对原数组的差分数组的两个数进行 -1(左侧的数) 和 +1(右侧的数)
或者是只对一个数 -1(区间包含最右侧)
将原数组变为全 0,即将差分数组全变为 0

为了得到最少操作数,最好先左侧正数 -1 右侧负数 +1

由于 target 所有的数都 >0
所以差分数组中 任意负数的左侧数字之和 都 >= abs(负数)
那么在 左侧正数 -1 右侧负数 +1时,必然是右侧负数先变为 0(或同时)
此时还需要进行 只对一个数 -1 操作,才能将正数变为 0
所以决定操作次数的是正数

总操作数就是差分数组中的正数之和
即原数组中 target[0] + 所有上升沿上升的大小


或者是我自己想出来的理解

在方法一中,注意到限制操作区间的是:操作过程中会有数据变为 0 从而分割区间
相较于一步步模拟直到出现 0 ,可以直接看出哪一个数据会先变为 0

如 [4,2,3,1,2,1,5]
先讲最左侧的数字变为 0 ,需要四次操作
将 4 变成 0 的操作中,4需要操作4次,而相邻右边的 2 只能操作两次之后就变成 0 了,从而分割了操作区间,也就是说这个 2 只能连接两次区间,也可以理解为只能向右传递两次操作
第三个数字 3 只能在数字 4 变成 0 的四次操作中传递到两次,即只能 -2,所以在四次操作之后为了将 3 变为 0 我们还需要额外进行一次操作

通过上述过程,注意到每一个数字本身的大小就代表着其能够传递的操作次数
如果其相邻右侧的数字小于(等于)自身,则是相邻右侧数字先(同时)变为 0 ,不需要额外操作次数
如果大于自身,则自身传递完操作之后相邻右侧数字还需要进行额外的操作才能变为 0 ,额外的操作次数为两数之差

也就是说,如果遇到了上升沿,就需要额外的 两数之差 操作次数

总操作数为先将最左边的数变为 0 ,即 target[0] 次,额外的操作数就是相邻两上升的数字之间的差值

问:为什么一定要是相邻的两个数字
答:因为每一个数字都有不同的传递次数,只能作用于相邻的数字
[4,2,3,1,2,1,5] 中的第二个 2 只能传递 2 次,并不意味着其右边所有的数都只能操作两次,因为其相邻右边的 3 可以传递 3次操作


代码如下↓

class Solution {
public:int minNumberOperations(vector<int>& target) {int n = target.size();int res = target[0];  // 初始化:首元素操作次数for (int i = 1; i < n; i++) {if (target[i] > target[i-1]) {// 累加上升沿的增量(差分正数项)res += target[i] - target[i-1];}}return res;}
};
http://www.dtcms.com/a/553675.html

相关文章:

  • Linux中伙伴系统页面回收free_pages_bulk和分配函数__rmqueue的实现
  • 33.点赞功能
  • 网站怎么快速做排名个人在线免费公司注册
  • 微信官网网站模板百度站长平台网页版
  • 黑马点评学习笔记03(Hutool工具库)
  • 太原模板建站系统无障碍网站建设标准
  • 企业级SQL审核优化工具 PawSQL 介绍(3)- 审核工单管理
  • XML文档差异分析工具:深入解析Word XML结构变化
  • 门户网站域名长治房产网站建设
  • 神经网络如何预测仓库拥堵?
  • 基于EasyExcel的动态列映射读取方案
  • 非凡免费建网站平台大型网站开发项目合同
  • 瑞芯微RK35xx升级RGA驱动版本和API版本
  • C++ 与 Go 相互调用实践指南:基于 SWIG + Director 模式
  • 做音乐的网站设计网站版权设置
  • SAP ABAP 视图表/表 表维护视图字段更新
  • 汇编、反汇编和机器码
  • 网站做跳转链接馆陶网站推广
  • 逻辑回归正则化解释性实验报告:L2 正则对模型系数收缩的可视化分析
  • LeetCode 412 - Fizz Buzz
  • 大型门户网站建设特点怎么知道一个网站是谁做的
  • IDC报告:阿里云市场份额升至26.8%,连续5季度上涨
  • 佛山房地产网站建设51建模网官方网站
  • 字格格子模板合集:多样练字格硬笔书法训练模板(可打印)
  • Arduino ESP32-C3 串口使用注意事项
  • MCP是什么及如何开发一个MCPServer
  • 程序逆向分析
  • 卷绕设备与叠片设备
  • 个人可以做购物网站吗西安曲江文化园区建设开发有限公司网站
  • 网站当前链接深圳坪地网站建设 自助建站 五合一建站平台