📌  相关文章
📜  制作给定数组 Bitonic 所需的最小移除量(1)

📅  最后修改于: 2023-12-03 15:22:44.982000             🧑  作者: Mango

制作给定数组 Bitonic 所需的最小移除量

Bitonic 数组是指一个先单调递增后单调递减或者是先单调递减后单调递增的数组。现在给定一个没有重复元素的整数数组,要求你在保证该数组是 Bitonic 数组的前提下,最少需要移除多少个元素。

解题思路

要想移除尽可能少的元素,我们需要做到以下两点:

  1. 保留元素个数尽量多,即尽量少的删除元素
  2. 保留的元素尽量分布在数组的两侧,这样才能保证该数组是 Bitonic 数组

所以,我们可以先分别将原数组按从小到大和从大到小排序,得到两个数组 $dp1$ 和 $dp2$,分别表示在以该元素为结尾的子数组中,单调递增和单调递减的最长子序列长度。

然后,我们可以枚举一个中枢点 $i$,计算在 $dp1$ 中以 $i$ 结尾的最长单调递增子序列长度 $l1$,在 $dp2$ 中以 $i$ 开头的最长单调递减子序列长度 $l2$,然后 $l1+l2-1$ 就是以 $i$ 为中心的最长 Bitonic 子序列长度(减 1 是因为 $i$ 被重复计算了)。将所有中枢点的最长 Bitonic 子序列长度求一下最大值,然后用数组长度减去该最大值,得到要删除的元素个数。

代码实现
def minimum_removals_bitonic(arr):
    n = len(arr)
    dp1, dp2 = [1] * n, [1] * n

    # 计算 dp1 和 dp2
    for i in range(1, n):
        for j in range(i):
            if arr[j] < arr[i]:
                dp1[i] = max(dp1[i], dp1[j] + 1)
            if arr[n - j - 1] < arr[n - i - 1]:
                dp2[n - i - 1] = max(dp2[n - i - 1], dp2[n - j - 1] + 1)

    # 计算最大的 Bitonic 子序列长度
    res = 0
    for i in range(n):
        l1, l2 = dp1[i], dp2[i]
        if l1 > 1 and l2 > 1:
            res = max(res, l1 + l2 - 1)

    return n - res

其中,时间复杂度为 $O(n^2)$,空间复杂度也为 $O(n^2)$。如果你想优化它,可以使用二分查找和贪心思想,将时间复杂度降至 $O(n \log n)$ 和空间复杂度降至 $O(n)$。