【问题标题】:Python - Matching two non-decreasing arraysPython - 匹配两个非递减数组
【发布时间】:2017-03-20 07:31:58
【问题描述】:

我正在研究以下问题: 注意:代码是在0.4秒的时间限制下工作,需要O(N+M)解 你的朋友给了你一个由 n 个正整数组成的列表:a0, a1, a2, ... an-1,按升序排列。

现在,你的朋友要问你 m 个问题,每个问题的形式是:“这是一个正整数 B。B 是列表的一部分吗?(B 是非递减顺序)强>”

你的任务是回答这些问题。输出一个整数,即你说“YES”的次数。

输入格式: 输入的第一行将包含整数 n。

输入的第二行将包含n个正整数,即列表a,按升序排列。

下一行输入将包含整数 m,即问题的数量。

接下来的 m 行输入将包含一个按非递减顺序排列的整数 B,这是您朋友询问您的正整数。

输出格式: 输出应包含一个整数,即您说“是”的次数。

这是我的代码:

n = int(raw_input())
a = [int(x) for x in raw_input().split()]
m = int(raw_input())
b = []
for y in range(0, m):
    b.append(int(raw_input()))

answer = 0
i = 0
j = 0
z = 1

while (i < n) and (j < m):
    if a[i] == b[j]:
        answer = answer + 1
        while ((z + j) < m):
            if a[i] == b[j + z]:
                answer = answer + 1
                z = z + 1
            elif a[i] != b[j + z]:
                i = i + 1
                j = j + z + 1
    elif a[i] < b[j]:
        i = i + 1
    elif a[i] > b[j]:
        j = j + 1

print answer

正如代码所暗示的那样,我正在尝试使用一种方法来比较数组 A 和数组 B 中的项目,如果它们不匹配,则在具有较小项目的数组的索引中添加一个。但是,代码没有输出正确的答案,有时会一直循环,要求我输入无限数量的输入。

我是编程初学者,我知道这是一个非常基础的算法。对于任何表述不够清晰或技术性不够的声明,我深表歉意。

谢谢。

【问题讨论】:

  • 您的逻辑对我来说似乎很模糊,您可能应该更详细地解释为什么您选择以自己的方式更新索引。同样,只要快速浏览一下您的代码,在我看来,您似乎忘记在需要时将索引重置为 0(zi)。最后你应该提供一个minimal reproducible example
  • @JulienBernu 我正在使用这种方法来提供在 0.4 秒时间限制下工作的 O(N+M) 解决方案。为了不重复地调用 A 和 B 的索引,每次两个项目“匹配”或“不匹配”时,i 和 j 必须加 1。 z 只是用来计算重复值的可能性,例如 B = [1, 2, 4, 4, 4, 4, 4, 5, 6]。请问您是否可以指出有关索引的任何错误,因为我怀疑这是发生错误的地方。谢谢。

标签: python arrays list search match


【解决方案1】:

我不会在这里使用 while 循环。这就是它运行无限时间的原因。只需使用for 循环。此外,python 语言中还有一些非常好的功能,可以让您比自己遍历整个列表更快地完成此操作。

In [6]: count = 0

In [7]: a = [1, 2, 3, 4, 5, 100]

In [8]: b = [1, 3, 1000, -10, 12]

In [9]: for val in b:
   ...:     if val in a:
   ...:         count += 1
   ...:

In [10]: print count
2

Julien Bernu 有一个更优雅的想法:

a = set([1, 2, 3, 4, 5, 100])
b = set([1, 3, 1000, -10, 12])
print len(a.intersection(b))

【讨论】:

  • @JulienBernu 请问这是如何工作的?谢谢。
  • @SunnyXu 这只是数学:你取 2 个集合的交集,即属于这两个集合的元素,然后计算有多少元素(len 这样做)。
  • 感谢您的回复。检查每个单个值的 for 循环会给出 O(N * M) 的算法复杂度,这会在这个问题上超时,因为我正在寻找一个算法复杂度为 O(N+M) 的代码,它可以工作对于所有值,A 为升序,B 为非降序。
  • @JulienBernu 谢谢。我尝试了 print len(list(set(a) & set(b))) 但是,问题以“非递减”顺序呈现 B,这意味着它可以重复,而 A 是不重复的列表。您是否知道使用 len 函数也可以添加 B 的重复值的任何方法?谢谢。
【解决方案2】:

您可以先在字典中跟踪每个元素在b 中出现的次数:

counts = {x: b.count(x) for x in b}
print sum(counts[x] for x in set(a).intersection(b))

【讨论】:

  • 谢谢。代码确实有效。但是,它没有在 0.4 秒的时间限制下运行,这需要 O(N+M) 解决方案。如果可能的话,如果您能在我原来的 O(N+M) 方法中找到改进或找出错误的方法,将不胜感激。谢谢。
【解决方案3】:

感谢大家的帮助。 @Greg @JulienBernu 我根据我的原始逻辑改进了我的代码并解决了这个问题。解决方案在 O(N+M) 中,所有输入都在 0.25 秒内工作。

n = int(raw_input())
a = [int(x) for x in raw_input().split()]
m = int(raw_input())
b = []
for y in range(0, m):
    b.append(int(raw_input()))

answer = 0
i = 0
j = 0

while (i < n) and (j < m):
    if a[i] == b[j]:
        answer = answer + 1
        j = j + 1
    elif a[i] < b[j]:
        i = i + 1
    elif a[i] > b[j]:
        j = j + 1

print answer

或者当 b 不是非递减顺序时对所有值的回答,检查列表 b 是否使用all(b[i] &lt;= b[i + 1] for i in xrange(m-1)) 排序。如果没有排序,就用我之前用过的二分查找的方法解决,O(Mlog(N))。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多