LeetCode1187. 使数组严格递增 [Hard]

1187. Make Array Strictly Increasing

Given two integer arrays arr1 and arr2 , return the minimum number of operations (possibly zero) needed to make arr1 strictly increasing.

In one operation, you can choose two indices 0 <= i < arr1.length and 0 <= j < arr2.length and do the assignment arr1[i] = arr2[j] .

If there is no way to make arr1 strictly increasing, return -1 .

Example 1:

Input: arr1 = [1,5,3,6,7], arr2 = [1,3,2,4]
Output: 1
Explanation: Replace 5 with 2, then arr1 = [1, 2, 3, 6, 7].

Example 2:

Input: arr1 = [1,5,3,6,7], arr2 = [4,3,1]
Output: 2
Explanation: Replace 5 with 3 and then replace 3 with 4. arr1 = [1, 3, 4, 6, 7].

Example 3:

Input: arr1 = [1,5,3,6,7], arr2 = [1,6,3,3]
Output: -1
Explanation: You can't make arr1 strictly increasing.

Constraints:

  • 1 <= arr1.length, arr2.length <= 2000
  • 0 <= arr1[i], arr2[i] <= 10^9

题目:给你两个整数数组 arr1arr2 ,返回使 arr1 严格递增所需要的最小「操作」数(可能为 0)。每一步「操作」中,你可以分别从 arr1arr2 中各选出一个索引,分别为 ij0 <= i < arr1.length0 <= j < arr2.length ,然后进行赋值运算 arr1[i] = arr2[j] 。如果无法让 arr1 严格递增,请返回 -1

思路:动态规划,参考link。和最长递增子序列类似。对于 arr1 中的每个元素,均有一个状态集合 mp ,如对于第 i 个元素,其状态集合为( s t a t e k state_k statek, c n t k cnt_k cntk),表示为了使 arr1[0...i] 严格递增,所需的操作数为 c n t k cnt_k cntk, 此时对应的 arr[i] 的值填充为 s t a t e k state_k statek。那么对于第 i+1 个元素(记其状态集合为 m ),如果 arr1[i+1] s t a t e k state_k statek大,那么操作数不变,由 c n t k cnt_k cntk决定;或者从 arr2 中查找比 s t a t e k state_k statek大的数,进行替换,此时操作数加1。

如例子2: arr1 = [1, 5, 3, 6, 7] , arr2 = [4, 3, 1] :

对于 arr1

初始状态: mp : (-1, 0)

i=0 时, arr1[i]=1mp : (1, 0), (1, 1), (3, 1), (4, 1) => (1, 0), (3, 1), (4, 1)

i=1 时, arr1[i]=5mp : (5, 0), (3, 1), (4, 1); (5, 1), (4, 2); (5, 1) => (5, 0), (3, 1), (4, 1)

i=2 时, arr1[i]=3mp : (4, 2)

i=3 时, arr1[i]=6mp : (6, 2)

i=4 时, arr1[i]=7mp : (7, 2)

工程代码下载

class Solution {
public:
    int makeArrayIncreasing(vector<int>& arr1, vector<int>& arr2) {
        sort(arr2.begin(), arr2.end());
        unordered_map<int, int> mp;
        mp[-1] = 0;

        for(auto num : arr1){
            unordered_map<int, int> m;
            for(auto state : mp){
                // state:(val, cnt)
                int prev_val = state.first, prev_cnt = state.second;
                // arr1中的值比状态state的数大,满足条件
                if(num > prev_val){
                    int cnt = m.count(num) == 0 ? INT_MAX : m[num];
                    m[num] = min(prev_cnt, cnt);
                }
                // 在arr2中的值找满足比当前state大的那个数,此时的操作数相对于状态state加1
                auto iter_idx = upper_bound(arr2.begin(), arr2.end(), prev_val);
                if(iter_idx != arr2.end()){
                    int num2 = *iter_idx;
                    int cnt = m.count(num2) == 0 ? INT_MAX : m[num2];
                    m[num2] = min(prev_cnt + 1, cnt);
                }
            }
            mp = m;
        }

        if(mp.empty())
            return -1;

        int res = INT_MAX;
        for(auto item : mp)
            res = min(res, item.second);
        return res;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值