📜  门| GATE-CS-2009 |问题24(1)

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

题目:GATE-CS-2009 | 问题24

题目描述

给定正整数n和整数序列A,则“短序列”是由序列A的k个连续元素(k是小于或等于n的正整数)形成的,其中1≤k≤n。未被短序列覆盖的序列A的元素数称为“暴露的”。设计一个算法,计算所有可能的短序列中暴露的元素数的最小值。

输入

第一行包含一个正整数n,表示序列A的最大长度。

第二行包含n个整数,表示序列A的元素。

输出

输出一个整数,即所有可能的短序列中暴露的元素数的最小值。

示例
输入
5
2 1 3 1 2
输出
2
解释

序列A中最少有两个元素是暴露的。例如,序列A的不同短序列及其尺寸为:

{2} -> 4暴露

{1} -> 3暴露

{3} -> 3暴露

{1} -> 3暴露

{2} -> 4暴露

{2, 1} -> 2暴露

{1, 3} -> 1暴露

{3, 1} -> 1暴露

{1, 2} -> 2暴露

{2, 1, 3} -> 0暴露

{1, 3, 1} -> 0暴露

{3, 1, 2} -> 1暴露

{1, 2} -> 2暴露

{2, 1} -> 2暴露

{2, 1, 3, 1} -> 0暴露

{1, 3, 1, 2} -> 0暴露

解题思路

首先,我们需要找到暴露元素的数量最小值。我们可以将原始数组拆分成所有可能的子序列,并找到暴露元素的数量。最后,我们需要找到这些元素的最小值。

让我们考虑一下如何构建所有可能的子序列。我们将遍历数组并找到每个元素的所有子序列。我们定义一个函数all_sub_lists(),该函数将返回当前元素的所有子序列。我们可以递归地找到所有可能的子序列。为了防止重复,我们标记已经考虑过的元素。

接下来,我们需要找到暴露元素的数量。我们可以在 all_sub_lists() 函数中找到每个子序列是否有暴露元素,并记录暴露元素的数量。最后,我们必须找到所有可能子序列的暴露元素数量的最小值。

我们可以使用递归函数short_seq()来构建所有可能的子序列,并计算每个子序列的暴露元素数量。我们将使用递归来构建短序列,并计算暴露元素数量。我们将跟踪已经考虑过的元素,以防止重复。

因此,我们的算法包括以下步骤:

  1. 定义 all_sub_lists() 函数,返回当前元素的所有子序列。
  2. 在 all_sub_lists() 函数中,递归调用自身并标记已经被考虑过的元素。
  3. 定义 short_seq() 函数,用递归构建所有可能的短序列。
  4. 在 short_seq() 函数中,找到每个可能的短序列的暴露元素数量。
  5. 在 short_seq() 函数中,跟踪已经考虑过的元素,以避免重复。
  6. 在 short_seq() 函数中,找到所有可能的短序列的暴露元素数量的最小值。
代码实现
def all_sub_lists(A, i, j, marked):
    temp = []
    for k in range(i, j + 1):
        if marked[k]:
            continue
        k_list = [A[k]]
        temp.append(k_list)
        marked[k] = True
        sublist = all_sub_lists(A, i, k - 1, marked)
        if sublist:
            for sub in sublist:
                new_sub = k_list + sub
                temp.append(new_sub)

    return temp


def short_seq(A, n, marked):
    min_exposed = float('inf')
    for i in range(n):
        for j in range(i, n):
            sub_lists = all_sub_lists(A, i, j, marked)
            for sub in sub_lists:
                exposed = 0
                for x in range(n):
                    if not marked[x] and A[x] not in sub:
                        exposed += 1
                if exposed < min_exposed:
                    min_exposed = exposed

    return min_exposed


n = int(input())
A = list(map(int, input().split()))
min_exposed = float('inf')
marked = [False for _ in range(n)]
print(short_seq(A, n, marked))
复杂度分析

该算法包括以下循环嵌套:

  1. 外层循环在i从0到n循环。
  2. 内部循环在j从i到n循环。
  3. 内部循环依次迭代所有可能的子序列,并计算暴露的元素数。因此,循环的次数取决于每个可能的子序列的长度和未选择的元素数量,最差情况下是O(n)。
  4. 最坏情况下,递归的all_sub_lists函数将调用O(n)次,因为每个元素只能出现一次。
  5. 因此,时间复杂度为O(n^4),空间复杂度为O(2^n)。