具有特定性质的最小字符串

时间:2019-03-21 20:15:06

标签: algorithm

假设我有N个正整数的字符串,其中包含K个不同的整数。例如,此字符串:1 3 1 3 1 3 3 2 2 1.对于此字符串,N = 10,K = 3(1,2,3 )。我想要的是找到包含所有K个整数的最小子字符串。在这种情况下,解决方案将是1 3 3 2或3 2 2 1。

我考虑过从左到右检查此字符串并创建一个新字符串。在此新字符串中,我将第一个整数命名为“ first”,并将其值与当时正在检查的每个整数进行比较。我要添加的内容与第一个元素相同,我从字符串中删除了第一个元素,并且first + 1元素成为新的`first。之后,我还需要检查first(previous first)之后的元素并检查如果first + 1和first + 2..first + n是相同的(fe 3 3 3)我会删除除第n个元素以外的所有元素。我还可以跟踪正在构建的列表中的不同元素并且当它达到K时,保持此值并仅在找到较小的子集时才更新它。但是,我认为这不是对此的最佳解决方案,并且我相信这可以在线性时间内完成。有什么想法?

1 个答案:

答案 0 :(得分:2)

这可以肯定地以线性方式完成。

首先,让我们找到命中所有K值的最短前缀,然后我们将删除第一项并扩大新的前缀,直到命中为止,依此类推。答案就是这些前缀的最小长度。

cnt[K] = {0, 0, ..., 0} # cnt[i] == how many times we hit value i
nonzero_cnt = 0 # how many different values we hit

hi = 0 # right border
ans = N+1 # len of shortest subsegment found so far, >N on init to be relaxated
for lo = [0, N):  # left border (or how many first elements we droped)
    while nonzero_cnt < N: # moving right border until subsegment is good
        if hi = N: STOP() # right border did all the way to boundary
        if cnt[hi] = 0:
            nonzero_cnt += 1
        cnt[hi] += 1
        hi += 1
    ans = min(ans, hi-lo)
    cnt[lo] -= 1 # left border moved to right by one
    if cnt[lo] = 0:
        nonzero_cnt -= 1