动态规划和贪心算法问题|豆包MarsCode AI刷题

71 阅读4分钟

问题描述

给定一个长度为 nn 的序列 a1,a2,…,ana1​,a2​,…,an​,你可以选择删去其中最多 n−1n−1 个数,得到一个新序列 b1,b2,…,bmb1​,b2​,…,bm​ (1≤m≤n1≤m≤n),新序列保留原来的相对顺序。你的目标是删除某些数,使得新序列的第 ii 个数 bi=ibi​=i。现在需要求出最少删除多少个数才能得到这样的序列,如果无法得到,输出 −1−1。

例如,对于序列 [1, 4, 2, 3, 5],删除第 2 个和第 5 个元素后,可以得到序列 [1, 2, 3]

解题思路

  1. 识别目标序列:我们需要找到一个子序列,使得这个子序列的元素是 [1, 2, 3, ..., k] 的形式。
  2. 计算删除次数:如果存在这样的子序列,计算需要删除的元素个数。如果不存在这样的子序列,返回 -1

代码步骤

我们可以通过以下步骤来实现这个算法:

  1. 遍历数组:遍历数组 a,尝试找到一个从1开始的连续递增子序列。
  2. 记录位置:使用一个数组或字典来记录每个数字的位置。
  3. 检查连续性:检查是否存在从1开始的连续递增子序列。
  4. 计算删除次数:如果存在这样的子序列,计算需要删除的元素个数。
def solution(n: int, a: list) -> int:
    # 记录每个数字的位置
    position = {}
    for i in range(n):
        position[a[i]] = i
    
    # 初始化最长连续子序列的长度
    max_len = 0
    
    # 遍历数组,尝试找到最长连续递增子序列
    for num in range(1, n + 1):
        if num in position:
            # 检查是否连续
            if num == 1 or (num - 1 in position and position[num] > position[num - 1]):
                max_len += 1
            else:
                break
        else:
            break
    
    # 如果最长连续子序列的长度为0,返回-1
    if max_len == 0:
        return -1
    
    # 计算需要删除的元素个数
    return n - max_len

if __name__ == '__main__':
    print(solution(5, [1, 4, 2, 3, 5]) == 2)
    print(solution(3, [3, 3, 2]) == -1)
    print(solution(5, [1, 2, 3, 4, 5]) == 0)

关键步骤

  • 记录位置:使用字典 position 记录每个数字的位置。
  • 检查连续性:遍历数字 1 到 n,检查是否存在连续递增的子序列。
  • 计算删除次数:如果存在连续递增的子序列,计算需要删除的元素个数。

这个问题属于动态规划贪心算法的结合题型。具体来说,它涉及到寻找一个最长的连续递增子序列,并计算需要删除的最少元素个数。

题型分类

  • 动态规划:用于寻找最优解,通常涉及状态转移和子问题最优解的组合。
  • 贪心算法:用于在每一步选择当前最优解,以期望最终得到全局最优解。

解题思路

  1. 理解问题:我们需要找到一个子序列,使得这个子序列的元素是 [1, 2, 3, ..., k] 的形式。
  2. 记录位置:使用一个数据结构(如字典)记录每个数字在原序列中的位置。
  3. 检查连续性:遍历数字 1 到 n,检查是否存在连续递增的子序列。
  4. 计算删除次数:如果存在连续递增的子序列,计算需要删除的元素个数。

解决方法

  1. 记录位置:使用字典 position 记录每个数字的位置。
  2. 遍历检查:从数字 1 开始,检查是否存在连续递增的子序列。
  3. 动态更新:如果当前数字 num存在且位置连续,则更新最长连续子序列的长度。
  4. 计算结果:根据最长连续子序列的长度,计算需要删除的元素个数。

关键点

  • 记录位置:使用字典 position 记录每个数字的位置。
  • 检查连续性:遍历数字 1 到 n,检查是否存在连续递增的子序列。
  • 动态更新:如果当前数字 num存在且位置连续,则更新最长连续子序列的长度。
  • 计算结果:根据最长连续子序列的长度,计算需要删除的元素个数。

通过这种方法,我们可以有效地解决这类问题。