找到包含所有数字的最小长度子阵列

时间:2016-05-12 18:31:15

标签: python arrays algorithm sub-array

文件input.txt由两行组成:首先是整数N空格,然后是整数K(1≤N,K≤250000)。第二个具有N个空格分隔的整数,其中每个整数小于或等于K.保证从1到K的每个整数都在数组中。任务是找到包含所有整数的最小长度的子数组。并打印它的开始和结束。请注意,索引从1开始。

示例:

Input         Output
5 3           2 4
1 2 1 3 2

6 4           2 6
2 4 2 3 3 1  

我在最近的一场编程比赛中完成了这项任务。结束了,我不是在作弊。我已经使用python 3实现了它:

with open('input.txt') as file:
    N, K = [int(x) for x in file.readline().split()]
    alley = [int(x) for x in file.readline().split()]

trees = {}
min_idx = (1, N)
min_length = N
for i in range(N):
    trees[alley[i]] = i
    if len(trees) == K:
        idx = (min(trees.values())+1, max(trees.values())+1)
        length = idx[1] - idx[0] + 1
        if length < min_length:
            min_idx = idx
            min_length = length
        if min_length == K:
            break


print (str(min_idx[0]) + " " + str(min_idx[1]))

这个想法是将第i个树的最后位置保存到字典中,如果字典包含所有项目,请检查该子数组是否最小。

第16次测试显示我的算法超过了时间限制,即1秒。我认为,我的算法是O(N),因为它在一次运行中完成,并且映射访问成本为O(1)。

如何加速此算法?可以降低复杂性,还是我对某些需要花费很多时间的Python的误解呢?

2 个答案:

答案 0 :(得分:2)

您的算法很好但忽略了len(trees) < K的时间,O(NK),因为对minmax的每次调用都是O(K)。无需拨打max,因为max(trees.values()) == i。处理min比较棘手,但如果您跟踪哪个键对应于最小索引,则只有在更新该键时才能重新计算它。

一个小问题是,并不总是需要检查您的上一个if

总体:

trees = {}
min_idx = (1, N)
min_length = N
first_index = -1
for i in range(N):
    trees[alley[i]] = i
    if len(trees) == K:
        if first_index == -1 or alley[first_index] == alley[i]:
            first_index = min(trees.values())
        idx = (first_index+1, i+1)
        length = idx[1] - idx[0] + 1
        if length < min_length:
            min_idx = idx
            min_length = length
            if min_length == K:
                break

答案 1 :(得分:0)

使整数数组计数[K],用零填充 保留一些变量 - 左索引L,右索引R(如你的idx [0]和idx [1]),零计数Z.
将L和R设为1,增加计数[A [1]],将Z设为K-1

移动R,递增计数[A [1]],如果零条目更新,递减Z ,直到Z变为0
此时子阵列[L..R]包含从K到

的所有值

现在移动L,递减计数离开窗口的值的条目。 如果某个条目变为0,则增加Z 。当Z变为非零时,停止移动L并再次移动R.

当R达到N且L停止时,处理结束。有效(R-L + 1)对的最小长度最小

Example run for your [1 2 1 3 2]

Move R
1 0 0  Z=2
1 1 0  Z=1
2 1 0  Z=1
2 1 1  Z=0
Move L
1 1 1  Z=0
1 0 1  Z=1 Stop moving L, check previous L,R pair 2,4
Move R
1 1 1  Z=0
move L
9 1 1  Z=1 Stop moving L, check previous L,R pair 3,5