📌  相关文章
📜  将给定数组转换为 Mountain Array 所需的最小移除量(1)

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

将给定数组转换为 Mountain Array 所需的最小移除量

Mountain Array 是指数组 A 满足:

题目描述:

给你一个整数数组 nums,请你返回将该数组转换为 Mountain Array 所需的最小操作次数。

如果不可行,则返回 -1。

为了更好的解释本题的思路,这里先定义下什么是Mountain Array。

Mountain Array 是指一个数组满足:

存在左侧的 i ,满足 arr[i] < arr[i + 1]

存在右侧的 j ,满足 arr[j - 1] > arr[j]

存在一个山峰元素,满足 arr[i] < arr[i + 1] > arr[i + 2] > … > arr[j - 1] > arr[j]

示例:

输入:nums = [1,3,1] 输出:0

输入:nums = [2,1,1,5,6,2,3,1] 输出:3

思路解析

题目描述给出了我们一个约束条件,要把一个数组变成Mountain Array,那么我们首先要保证它本身数组是符合Mountain Array的定义,那这里我们可以采用双指针的形式满足第一个条件和第二个条件,即左右两指针从数组两端开始并行向中间移动,找到第一个左边小于右边的位置,第一个右边大于左边的位置,那么这时候整个数组被分成两个区间,左右两区间分别都是单调递增的。接下来我们需要找到一个位置分割出左右两区间,满足左区间的最大值小于山峰的那个位置,右区间的最大值大于山峰的那个位置。

代码实现

下面是Python3的代码实现,具体的解析在代码注释中:

class Solution:
    def minimumMountainRemovals(self, nums: List[int]) -> int:
        n = len(nums)
        # 满足 MountainArray 的数列的长度至少为 3 
        if n < 3:
            return -1
        
        # 构造辅助数组,lis 表示数组 nums 从左到右的最长上升子序列
        # lds 表示数组 nums 从右到左的最长上升子序列
        lis, lds = [1] * n, [1] * n
        for i in range(n):
            for j in range(i):
                if nums[i] > nums[j]:
                    lis[i] = max(lis[i], lis[j] + 1)
        for i in range(n - 1, -1, -1):
            for j in range(i + 1, n):
                if nums[i] > nums[j]:
                    lds[i] = max(lds[i], lds[j] + 1)
        res = 0
        # 枚举山顶的位置
        for i in range(1, n - 1):
            # 满足左右两边都有合法的子序列,更新 res 的值
            if lis[i] > 1 and lds[i] > 1:
                res = max(res, lis[i] + lds[i] - 1)
        # 计算需要移除的最小数目
        return n - res