假设我有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时,保持此值并仅在找到较小的子集时才更新它。但是,我认为这不是对此的最佳解决方案,并且我相信这可以在线性时间内完成。有什么想法?
答案 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