【每日一题】使数组严格递增

本文介绍了一种动态规划的方法来解决使数组严格递增的问题。通过记录前缀递增序列的最小末尾值,计算在不超过一定替换次数的情况下,能否使数组严格递增,最终给出最小的操作次数。文章探讨了朴素解法和维度压缩两种策略,分析了它们的时间和空间复杂度。
摘要由CSDN通过智能技术生成

1187. 使数组严格递增

关键词:动态规划、数组、递增序列

题目来源:1187. 使数组严格递增 - 力扣(Leetcode)

题目描述
T动态规划

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

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

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

输入:arr1 = [1,5,3,6,7], arr2 = [1,3,2,4]
输出:1
输入:arr1 = [1,5,3,6,7], arr2 = [4,3,1]
输出:2
输入:arr1 = [1,5,3,6,7], arr2 = [1,6,3,3]
输出:-1
解释:无法使 arr1 严格递增。
数据范围
1 <= arr1.length, arr2.length <= 2000
0 <= arr1[i], arr2[i] <= 10^9
朴素求解

(后续讨论,数组下标均从1开始,代码中数组下标依题目从0开始,注意转换)

先考虑能不能构成递增数组。

对于每一个数都需要考虑要不要替换,假设当前考虑到a[i]

  • 若保留a[i],则a[i]至少要大于前i-1个数构成的递增数组的末尾值,否则不能保留

    前i-1个数构成的递增数组可能有多个,对应的末尾值也有多个,为了尽量保留a[i],取最小的末尾值进行比较即可。

  • 若替换a[i],则用于替换的元素必须大于前i-1个数构成的递增数组的末尾值,不存在这样的元素则不能替换

    前i-1个数构成的递增数组可能有多个,对应的末尾值也有多个,为了尽可能的使得后面好构成递增数组,当前用于替换的元素应该尽可能小,故取最小的末尾值进行比较即可。

始终记住,我们只需要尽可能地凑出一个答案即可,所以上述的末尾值均取最小,从而使得后续尽可能地构造递增数组。

上述两种情况都用到“最小末尾值”,于是“记录末尾最小值”,设f[i]=前i个元素构成的所有递增数组中的末尾值的最小值。当前i个数(经过多次替换)不能构成递增数组时,f[i]即为INF。

若保留a[i],则第i个位置仍为a[i],若替换a[i],则第i个位置为替换后的元素,f(i)取二者的较小值。

再考虑最小操作次数。

由于f[i]的值已经被定义为“最小末尾值”,因此需要增加一维用于记录操作次数,对数组f修改如下

设f(i,j)=前i个数,经过j次替换后,得到的递增数组的末尾元素的最小值,对于a[i]

  • 若保留a[i],则a[i]必须严格大于f(i-1, j),则f(i,j)=a[i]
  • 若替换a[i],则替换后的元素必须严格大于f(i-1, j),且尽可能小,则f(i,j)为替换后的元素

同样,若前i个数无法通过j次替换得到严格递增数组,则将f(i,j)标记为INF。于是,第一个不等于INF的f(n, j)即为最终答案。

int makeArrayIncreasing(vector<int> &arr1, vector<int> &arr2) {
   
    int INF = 0x3f3f3f3f;
    // 预处理arr2:排序去重
    sort(arr2.begin(), arr2.end());
    arr2.erase(unique(arr2.begin(), arr2.end()), arr2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值