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

查找包含集合中所有值的最短连续子数组的算法

班思源
2023-03-14

我有以下问题要解决:

给定一组整数,例如{1,3,2}和一个随机整数数组,例如。

[1, 2, 2, -5, -4, 0, 1, 1, 2, 2, 0, 3,3]

找出包含集合中所有值的最短连续子数组。如果找不到子数组,则返回一个空数组。

结果:[1,2,2,0,3]

或者

< code>[1,2,2,-5,-4,3,1,1,2,0],{1,3,2}。

结果:[3,1,1,2]

我已经尝试了以下方法,我的第二个循环似乎有问题。我不确定我需要更改什么:

def find_sub(l, s):
    i = 0
    counts = dict()
    end = 0
    while i < len(s):
        curr = l[end]
        if curr in s:
            if curr in counts:
                counts[curr] = counts[curr] + 1
            else:
                counts[curr] = 1
                i += 1
        end += 1
    curr_len = end

    start = 0
    for curr in l:
        if curr in counts:
            if counts[curr] == 1:
                if end < len(l):
                    next_item = l[end]
                    if next_item in counts:
                        counts[next_item] += 1
                    end += 1
            else:
                counts[curr] -= 1
                start += 1
        else:
            start += 1
    if (end - start) < curr_len:
        return l[start:end]
    else:
        return l[:curr_len]

共有3个答案

易修洁
2023-03-14

这应该是性能最好的解决方案,在O(n)中运行:

def find_sub(l, s):
    if len(l) < len(s):
        return None

    # Keep track of how many elements are in the interval
    counters = {e: 0 for e in s}

    # Current and best interval
    lo = hi = 0
    best_lo = 0
    best_hi = len(l)

    # Increment hi until all elements are in the interval
    missing_elements = set(s)
    while hi < len(l) and missing_elements:
        e = l[hi]
        if e in counters:
            counters[e] += 1
        if e in missing_elements:
            missing_elements.remove(e)
        hi += 1

    if missing_elements:
        # Array does not contain all needed elements
        return None

    # Move the two pointers
    missing_element = None
    while hi < len(l):
        if missing_element is None:
            # We have all the elements
            if hi - lo < best_hi - best_lo:
                best_lo = lo
                best_hi = hi

            # Increment lo
            e = l[lo]
            if e in counters:
                counters[e] -= 1
                if counters[e] == 0:
                    missing_element = e
            lo += 1
        else:
            # We need more elements, increment hi
            e = l[hi]
            if e in counters:
                counters[e] += 1
                if missing_element == e:
                    missing_element = None
            hi += 1

    return l[best_lo:best_hi]


assert find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 0, 3, 3], {1, 3, 2}) == [2, -5, -4, 3, 1]
assert find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 1, 0, 3, 3], {1, 3, 2}) == [2, 1, 0, 3]
assert find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 1, 0, 3, 3], {1, 3, 7}) is None
匡凌
2023-03-14

您可以使用滑动窗口方法(使用生成器),其思想是生成大小为N(集合的大小)到大小为N(列表的大小)的所有子集,并检查它们是否存在,当找到第一个时停止:

from itertools import islice, chain

def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result    
    for elem in it:
        result = result[1:] + (elem,)
        yield result


l = [1, 2, 2, -5, -4, 3, 1, 1, 2, 0]
s = {1,3,2}

def minimum_subset(l, s):
    for w in chain.from_iterable(window(l, i) for i in range(len(s), len(l)+1)):
        if s == set(w):
            return w
    return []

print(minimum_subset(l, s))

结果(3,1,1,2)这里有一个真实的例子

曾华翰
2023-03-14

您使用的是双指针方法,但是只移动两个索引一次——直到找到第一个匹配。您应该重复< code >右移-左移模式,以获得最佳步进间隔。

def find_sub(l, s):
    left = 0
    right = 0
    ac = 0
    lens = len(s)
    map = dict(zip(s, [0]*lens))
    minlen = 100000
    while left < len(l):
        while right < len(l):
            curr = l[right]
            right += 1
            if curr in s:
                c = map[curr]
                map[curr] = c + 1
                if c==0:
                    ac+=1
                    if ac == lens:
                        break
        if ac < lens:
            break

        while left < right:
            curr = l[left]
            left += 1
            if curr in s:
                c = map[curr]
                map[curr] = c - 1
                if c==1:
                    ac-=1
                    break

        if right - left + 1 < minlen:
            minlen = right - left + 1
            bestleft = left - 1
            bestright = right

    return l[bestleft:bestright]

print(find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 0, 3, 3], {1,3,2}))
print(find_sub([1, 2, 2, -5, -4, 3, 1, 0, 1, 2, 2, 1, 0, 3, 3], {1,3,2}))
>>[2, -5, -4, 3, 1]
>>[2, 1, 0, 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,因为我们正

  • 我有个算法问题。我试图从一个更大的值集合中找到所有唯一的值子集。 例如,假设我有集。我能用什么算法找到3的这些子集? 子集不应重复,且顺序不重要,因此集{1,2,3}与集{3,2,1}相同。鼓励使用Psudocode(或常规类型)。

  • 文件输入。txt由两行组成:第一行是整数N空格,然后是整数K(1 ≤ N、 K级≤ 250000). Second有N个空间除数的整数,其中每个整数都小于或等于K。保证从1到K的每个整数都在数组中。任务是找到包含所有整数的最小长度的子数组。并打印其开始和结束。请注意,索引从1开始。 示例: 我在最近的一次编程比赛中完成了这个任务。一切都结束了,我没有作弊。我已经使用python 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 首先想到的是一个明显的强力(

  • 下面的代码实现了O(n^2)的时间复杂度。我希望能够在O(n)中完成。 例如,给定阵列[-2,1,-3,4,-1,2,1,-5,4],连续子阵列[4,-1,2,1]具有最大和= 6。

  • 问题内容: 如何在N个可变长度的JavaScript数组中生成值的所有组合? 假设我有N个JavaScript数组,例如 (在此示例中为三个数组,但针对该问题的数组数为N。) 我想输出其值的所有组合,以产生 编辑:这是我使用ffriend接受的答案作为基础的版本。 问题答案: 这不是排列,请参阅Wikipedia中的排列定义。 但是您可以通过 递归 实现: 您也可以使用循环来实现,但是这会有些棘手