当前位置: 首页 > 知识库问答 >
问题:

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

拓拔谭三
2023-03-14

文件输入。txt由两行组成:第一行是整数N空格,然后是整数K(1 ≤ N、 K级≤ 250000). Second有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个答案

杨景山
2023-03-14

使整数数组计数[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-L1)对最小

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
彭高畅
2023-03-14

你的算法很好,但是忽略了len(tree)的时间

一个次要的问题是,您的最后一个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

 类似资料:
  • 给定一个整数N和一个长度为N的数组,该数组由0到N-1的整数组成,可能包含也可能不包含所有整数,也可能包含重复数。查找一个从索引i到索引j的子数组(i, j),使其包含数组中的所有整数,并且具有最小长度。输出是这样一个子数组的长度 示例:A=[2,1,1,3,2,1,1,3],因此最小子数组长度=3,因为A[2]到A[4]包含所有数字 我的想法: 维护一个计数器数组和两个索引开始和结束,其中包含数

  • 给定一个整数数组,包含不超过两个不同值的最长子数组的长度是多少,使得非重复值的差异不超过 1? 例: 最大的子数组长度为4:[1,2,1,2]。 最大的子阵列具有长度4:[3,3,2,2]。值1和3相差1以上,因此[1,1,1,3,3]无效。

  • 假设我们有一个数组 {7, 3, 7, 3, 1, 3, 4, 1}。我需要的是一个算法(最好是一些 C 代码示例),它将返回包含数组所有元素的最小子数组的长度。 在这种情况下,它将是 5:{7, 3, 1, 3, 4},这是原始数组的最短子数组,其中包含数组的所有元素,即 1、3、4 和 7。 此外,数组 {2, 1, 1, 3, 2, 1, 1, 3} 的另一个示例,算法应返回 3,因为我们正

  • 我正在尝试解决这个算法问题: https://dunjudge.me/analysis/problems/469/ 为了方便起见,我总结了下面的问题陈述。 给定一个长度为 ( 多数元素定义为发生的元素 时限:1.5s 例如: 如果给定的数组是[1,2,1,2,3,2], 答案是5,因为从位置1到5 (0索引)的长度为5的子数组[2,1,2,3,2]具有出现为3的数字2 首先想到的是一个明显的强力(

  • 例如:如果数组是[9,8,7,6,5,4,3,1,2,2],它应该返回46(长度为7的子数组[9,8,7,6,5,4,3]和长度为2的子数组[2,2]之和)。不能组合[9,8,7,6,5,4,3]和[1,2,2],因为这将产生长度为10的非素数的连续子数组(幂等性)。 有谁能解释一下如何使用DP来解决这类问题吗?多谢了。

  • 这是一个面试问题。 我们被赋予各种矩形的尺寸,我们必须找出可以包围所有矩形的矩形面积(最小值)?矩形也可以旋转。 在将矩形拟合到最小可能区域之前,我曾问过一个类似的问题。 上述方法考虑了所有可能性、旋转,并在所有布局情况下确定了所有此类可能性的最小值<我们不能先求矩形面积之和,然后再求最大长度、最大宽度吗?