【1187. 使数组严格递增】

news2024/9/30 9:33:49

来源:力扣(LeetCode)

描述:

给你两个整数数组 arr1arr2,返回使 arr1 严格递增所需要的最小「操作」数(可能为 0)。

每一步「操作」中,你可以分别从 arr1arr2 中各选出一个索引,分别为 ij0 <= i < arr1.length0 <= j < arr2.length,然后进行赋值运算 arr1[i] = arr2[j]

如果无法让 arr1 严格递增,请返回 -1

示例 1:

输入:arr1 = [1,5,3,6,7], arr2 = [1,3,2,4]
输出:1
解释:用 2 来替换 5,之后 arr1 = [1, 2, 3, 6, 7]

示例 2:

输入:arr1 = [1,5,3,6,7], arr2 = [4,3,1]
输出:2
解释:用 3 来替换 5,然后用 4 来替换 3,得到 arr1 = [1, 3, 4, 6, 7]

示例 3:

输入:arr1 = [1,5,3,6,7], arr2 = [1,6,3,3]
输出:-1
解释:无法使 arr1 严格递增。

提示:

  • 1 <= arr1.length, arr2.length <= 2000
  • 0 <= arr1[i], arr2[i] <= 109

方法:动态规划

思路与算法

首先我们思考一下,由于要求数组严格递增,因此数组中不可能存在相同的元素,对于数组 arr2 来说,可以不需要考虑数组中的重复元素,可以预处理去除 arr2 的重复元素,假设数组 arr1 的长度为 n,数组 arr2 的长度为 m,此时可以知道最多可以替换的次数为 min(n, m)。如何才能定义动态规划的递推公式,这就需要进行思考。我们设 dp[i][j] 表示数组 arr1中的前 i 个元素进行了 j 次替换后组成严格递增子数组末尾元素的最小值。当我们遍历 arr1的第 i 个元素时,此时 arr1[i] 要么进行替换,要么进行保留,实际可以分类进行讨论:

此时如果 arr1[i] 需要进行保留,则 arr1[i] 一定严格大于前 i − 1 个元素替换后组成的严格递增子数组最末尾的元素。假设前 i − 1 个元素经过了 j 次变换后得到的递增子数组的末尾元素的最小值为 dp[i − 1][j],如果满足 arr1[i] > dp[i − 1][j],则此时 arr1[i] 可以保留加入到该子数组中且构成的数组严格递增;
此时如果 arr1[i] 需要进行替换,则替换后的元素一定严格大于前 i − 1 个元素替换后组成的严格递增子数组最末尾的元素。假设前 i − 1 个元素经过了 j − 1 次变换后得到的递增子数组的末尾元素的最小值为 dp[i − 1][j − 1],此时我们从 arr2 找到严格大于 dp[i − 1][j − 1] 的最小元素 arr2[k],则此时将 arr2[k] 加入到该子数组中且构成数组严格递增;
综上可知,每个元素在替换时只有两种选择,要么选择保留当前元素 arr1 ,要么从 arr2 中选择一个满足条件的最小元素加入到数组中,最少替换方案一定包含在上述替换方法中。我们可以得到以下递推关系:

1

为了便于计算,我们将 dp[i][j] 的初始值都设为 ∞,为了便于计算在最开始加一个哨兵,此时令 dp[0][0] = −1 表示最小值。实际计算过程如下:

  • 为了方便计算,需要对 arr2 进行预处理,去掉其中的重复元素,为了快速找到数组 arr2 中的最小元素,还需要对 arr2 进行排序;
  • 依次尝试计算前 i 个元素在满足 j 次替换时的最小元素:
    • 如果当前元素 arr1[i] 大于 dp[i][j − 1],此时可以尝试将 arr1[i] 替换为 dp[i][j],即此时 dp[i][j] = min(dp[i][j], arr1[i])。
    • 如果前 i − 1 个元素可以满足 j − 1 次替换后成为严格递增数组,即满足 dp[i − 1][j − 1] ≠ ∞,可以尝试在第 j 次替换掉 arr1[i],此时根据贪心原则,利用二分查找可以快速的找到严格大于 dp[i − 1][j − 1] 的最小值进行替换即可。
  • 设当前数组 arr1[i] 的长度为 n,如果前 n 个元素满足 j 次替换后成为严格递增数组,此时我们找到最小的 j 返回即可。

代码:

constexpr int INF = 0x3f3f3f3f;

class Solution {
public:
    int makeArrayIncreasing(vector<int>& arr1, vector<int>& arr2) {
        sort(arr2.begin(), arr2.end());
        arr2.erase(unique(arr2.begin(), arr2.end()), arr2.end());
        int n = arr1.size();
        int m = arr2.size();
        vector<vector<int>> dp(n + 1, vector<int>(min(m, n) + 1, INF));
        dp[0][0] = -1;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= min(i, m); j++) {
                /* 如果当前元素大于序列的最后一个元素 */
                if (arr1[i - 1] > dp[i - 1][j]) {
                    dp[i][j] = arr1[i - 1];
                }
                if (j > 0 && dp[i - 1][j - 1] != INF) {
                    /* 查找严格大于 dp[i - 1][j - 1] 的最小元素 */
                    auto it = upper_bound(arr2.begin() + j - 1, arr2.end(), dp[i - 1][j - 1]);
                    if (it != arr2.end()) {
                        dp[i][j] = min(dp[i][j], *it);
                    }
                }
                if (i == n && dp[i][j] != INF) {
                    return j;
                }
            }
        }
        return -1;
    }
};

执行用时:48 ms, 在所有 C++ 提交中击败了64.81%的用户
内存消耗:35.6 MB, 在所有 C++ 提交中击败了51.85%的用户
复杂度分析
时间复杂度:O(n × min(m, n) × logm),其中 n 表示数组 arr1 的长度,m 表示数组 arr2 的长度。每次替换时,我们都需利用二分查找找到最小的元素,此时需要的时间为 O(logm),最多需要尝试 n × min(m, n) 种替换方案,因此总的时间复杂度为 O(n × min(m, n) × logm)。
空间复杂度:O(n × min(m, n)),其中 n 表示数组 arr1 的长度,m 表示数组 arr2 的长度。我们需要保存每个子数组中替换次数下的末尾元素的最大值,一共最多有 n 个子数组,每个子数组替换替换的次数最多为 min(n, m) 次数,因此空间复杂度为 O(n×min(m,n))。
author:LeetCode-Solution

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

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

相关文章

如何在苹果Mac OS系统中安装MT4电脑版软件?

很多投资者可能已经发现了&#xff0c;当前市面上绝大部分的正规交易平台&#xff0c;都在使用MT4电脑版软件作为平台专用的交易工具。而市面上的电脑系统主要又分为微软Windows系统和苹果Mac OS系统&#xff0c;对于微软Windows系统的MT4电脑版软件安装&#xff0c;想必大家都…

若依Linux环境部署

若依Linux环境部署 1.若依项目2.后端3.Linux环境配置4.环境部署附录 1.若依项目 若依官网若依文档前后端分离代码 2.后端 整体项目结构 自己创建好数据库&#xff0c;并在如下地方修改代码 日志路径也需要修改 数据库建表语句 同时redis也要启动并配置好 后端启动 3.…

高级篇三、用户与权限管理

第03章_用户与权限管理.pdf 1、用户管理 1.1 登录MySQL服务器 mysql -h xxx -P xxx -u xxx -p DatabaseName –e "SQL语句"下面详细介绍命令中的参数&#xff1a; -h参数 后面接主机名或者主机IP&#xff0c;hostname为主机&#xff0c;hostIP为主机IP。-P参数 后…

如何在Google Play设置置顶大图

应用的置顶大图是Google Play商店上ASO优化的重要一环&#xff0c;是我们保持品牌形象的重要场所。如果我们没有设置预览视频&#xff0c;那么Google Play 将会使用置顶大图&#xff0c;如果添加了预览的视频&#xff0c;那么视频会放置在置顶大图的顶部。 添加游戏或应用程序…

关于Redis的BigKey

文章目录 准备keys * 等命令的危害与避免不用keys * &#xff0c;应该用什么BigKey阿里云Redis开发规范多大算Big危害怎么产生的&#xff1f;怎么发现BigKey怎么删除String类型使用hscan每次获取少量field-value&#xff0c;再使用hdel删除每个field使用ltrim渐进式逐步删除&am…

管理后台项目-02-平台属性组件模块

目录 1-分类三级列表 2-属性列表 2.1-需求功能分析 2.2-功能代码实现数据获取和变动 2.3-动态渲染数据 3-新增修改属性 3.1-点击新增属性逻辑处理 3.2-点击列表页面修改属性逻辑 3.3-新增和修改属性 3.4-点击删除属性值 3.5-点击删除属性 1-分类三级列表 需求&…

通过案例来了解响应式开发的音频控件

目录 前言 一、视频控件的使用方法 1.语法 2、部分功能介绍 二、案例举例 三、播放效果 前言 1.本文讲解的响应式开发技术&#xff08;HTML5CSS3Bootstrap&#xff09;的HTML5表单等功能方法的代码&#xff0c;这也是很多教材的一个典型案例&#xff1b; 2.本文将讲解涉…

IMX6ULL裸机篇之中断实验-通用中断驱动说明二

一. 通用中断驱动 本文是 IMX6ULL 裸机篇---中断实验。旨在用 C 语言编写一套简单的中断驱动框架代码。 在 start.S 文件中&#xff0c;我们在中断服务函数 IRQ_Handler 中调用了 C 函数 system_irqhandler 来处 理具体的中断。 本实验会认识中断控制器&#xff1a;…

RT-DETR论文学习笔记(DETRs Beat YOLOs on Real-time Object Detection)

论文地址&#xff1a;https://arxiv.org/abs/2304.08069 代码地址&#xff1a;GitHub - PaddlePaddle/PaddleDetection: Object Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time mult…

完美解决丨ValueError: time data ‘2018/12/24‘ does not match format ‘%Y/%m/%d‘

这里我选择的是&#xff1a; python from datetime import datetime date datetime.strptime(2018/12/24, %Y/%m/%d) 如果你可以执行这段代码&#xff0c;那么你可能会收到这样的报错&#xff1a; python Traceback (most recent call last): File "C:\Users\Administra…

机器学习中最基本的概念之一:数据集、样本、特征和标签

本文重点 数据集、样本、特征和标签是机器学习中的重要概念,这些概念在机器学习算法的设计和实现过程中起着至关重要的作用。在本文中,我们将对这些概念进行详细的讲解,以便更好地理解机器学习算法的基本原理和应用。 一、数据集 数据集是机器学习中最基本的概念之一,它…

VUE3 取Slot元素方法

VUE3 取Slot元素方法 话说前面,这方法诡异的很…尽量不要用. 我这里要实现一个对slot元素进行方法拓展的事情 就比如说我要给一个元素添加自定义拖放事件,正常来说大概是这样的 //vue3 <template><div class"custom" ref"el"><slot> …

Visual Instruction Tuning: 用LLaVA近似多模态GPT-4

©Paperweekly 原创 作者 | Chunyuan Li 使用 GPT-4 进行视觉指令学习&#xff01;Visual Instruction Tuning with GPT-4! ▲ Generated by GLIGEN (https://gligen.github.io/): A cute lava llama and glasses 我们分享了 LLaVA (Language-and-Vision Assistant)&#…

linux工具gcc/g++/gdb/git的使用

目录 gcc/g 基本概念 指令集 函数库 &#xff08;重要&#xff09; gdb使用 基本概念 指令集 项目自动化构建工具make/makefile 进度条小程序 ​编辑 git三板斧 创建仓库 git add git commit git push git status git log gcc/g 基本概念 gcc/g称为编译器…

集合详解之(五)Map集合

文章目录 &#x1f412;个人主页&#x1f3c5;JavaSE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;Map集合的介绍&#x1fa85;如何保证键的不重复性&#xff1f;&#xff08;equals()与hashCode()方法的联用&#xff09;&#x1f380;HashMap集合及常用方法&#x1f38…

电能计量自动化系统在用电管理上的应用

【摘要】&#xff1a;电能计量自动化系统在用电管理上的应用&#xff0c;不仅能够实现远程自动抄表&#xff0c;减少企业在人力资源成本上的投入&#xff0c;切实地维护企业的核心利益&#xff0c;创造出更多的经济效益。还能够通过装置在线监测与配网防窥电功能实现对电能计量…

D. Tokitsukaze, CSL and Stone Game(博弈)

Problem - D - Codeforces 时津风和CSL正在玩一个石头的小游戏。 一开始&#xff0c;有n个石子堆&#xff0c;其中第ii堆有aiai石子。两位玩家轮流走棋。时津风先走。每一回合&#xff0c;棋手选择一个非空的棋堆&#xff0c;并从该棋堆中准确地取出一块石头。如果在轮到他之前…

2 路 500MSPS/1GSPS/1.25GSPS 14 位直流耦合 AD 采集 FMC 子卡模块

板卡概述 FMC155 是一款基于 VITA57.1 标准的&#xff0c;实现 2 路 14-bit、 500MSPS/1GSPS/1.25GSPS 直流耦合 ADC 同步采集 FMC 子卡模 块。该模块遵循 VITA57.1 规范&#xff0c;可直接与 FPGA 载卡配合使用&#xff0c;板 卡 ADC 器件采用 ADI 的 AD9680 芯片&#xf…

Python每日一练(20230420)

目录 1. 数组逐位判断 &#x1f31f; 2. 交错字符串 &#x1f31f;&#x1f31f; 3. 二进制求和 &#x1f31f; 4. 四舍六入五成双规则 &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 J…

12、HOOK原理下

一、去符号和恢复符号 1.1 Stip和 Strip Type解释 strip在iOS中的作用是 剥掉目标文件中一些符号信息和调试信息&#xff0c;使文件变小。dead code strip &#xff1a; 死代码剥离、然后再去链接。那么strip在哪些地方不能起作用呢&#xff1f; 动态库 不能strip全局符号、因…