leetcode 1187. Make Array Strictly Increasing [DP]

description

和最长递增子序列(LIS)思路很像。
对于位置 i ,其取值要满足单调递增的约束,最多有两种情况:

  1. arr1[i]
  2. 来自arr2

当位于i+1时,首先查看位置 i 的所有可能取值x,若arr1[i+1]大于x,则arr[i+1]满足单调递增且不会产生操作;若arr1[i+1]<=x,则arr[i+1]不满足单调递增。然后在arr2中寻找第一个大于x的值,该值满足单调递增,但会在x的基础上增加一次操作。

这样我们可以通过位置 i 来推出位置 i+1 。所以每个位置 i 需要一个字典dp,它的keys为当前位置的可能取值,values为对应取值的操作数。问题的解即是最后位置对应dp的values的最小值。

举个例子:

Input: arr1 = [1,5,3,6,7], arr2 = [1,3,4]

位置01234
dp{1:0}{5:0, 3:1}{4:2}{6:2}{7:2}
含义位置0可取0,需要0次操作位置1可取5,需要0次操作
位置1可取3,需要1次操作
位置2可取4,需要2次操作位置3可取6,需要2次操作位置4可取7,需要2次操作
class Solution:
    def makeArrayIncreasing(self, arr1: List[int], arr2: List[int]) -> int:
        dp = {-1:0}
        arr2.sort()
        for i in arr1:
            tmp = collections.defaultdict(lambda: float('inf'))
            for key in dp:
                if i > key:
                    tmp[i] = min(tmp[i],dp[key])
                loc = bisect.bisect_right(arr2,key)
                if loc < len(arr2):
                    tmp[arr2[loc]] = min(tmp[arr2[loc]],dp[key]+1)
            dp = tmp
        if dp:
            return min(dp.values())
        return -1

还有一种将dp的key、value含义反转的写法(比上面快了4×),即key表示操作数,value表示取值。如果上一种写法看懂了的话,应该也能看懂这个。

class Solution:
  def makeArrayIncreasing(self, arr1, arr2) -> int:
    N = len(arr1)
    arr2.sort()
    dp = {0: arr1[0], 1: arr2[0]}
    for i in range(1, N):
      tmp = collections.defaultdict(lambda: float('inf'))
      for k, v in dp.items():
        if v < arr1[i]:
          tmp[k] = min(tmp[k], arr1[i])
        p = bisect.bisect_right(arr2, v)
        if p < len(arr2):
          tmp[k + 1] = min(tmp[k + 1], arr2[p])
      dp = tmp
    if len(dp) == 0:
      return -1
    return min(dp.keys())
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值