【问题标题】:Find first element match between two sequences in linear time?在线性时间内找到两个序列之间的第一个元素匹配?
【发布时间】:2016-01-26 19:40:02
【问题描述】:

假设我们有两个序列 x = {x_i : i elem [1,M]} 和 y = {y_i : i elem [1,N]} 有一个有序的字母表。是否有可能找到满足 x_i = y_j 的最小(如果有)对 (i, j)?

简单的 O(n^2) 时间 O(1) 空间算法只是让您比较任一序列的每个元素,同时跟踪与序列开始的距离的最小差异。

O(n log n) 时间 O(n) 空间算法只是对序列进行排序和比较,同时保持跟踪最小/最大元素。

虽然我想不出线性时间算法,我不确定这个问题会被称为什么。

【问题讨论】:

  • 它可以在 O(max{m,n}log(min{m,n})) 中完成,方法是只对较小的列表进行排序,并在迭代较大的列表时对其使用二进制搜索。我很确定它与克服 nlogn 边界的元素区别问题太相似(除非允许散列并且便宜)

标签: string algorithm big-o time-complexity


【解决方案1】:

首先,请注意它可以在O(max{m,n}log(min{m,n})) 中完成,方法是只对较小的列表进行排序,并在迭代较大的列表时对其使用二进制搜索。

此外,您可以使用哈希表将一个列表索引到对 x_i->min{j, x_j = x_i } - 这需要预期的线性时间和空间。
然后,只需迭代另一个列表,并在表中查找y_i,同时保持目前找到的最小值。

这在平均情况下总共需要 O(n) 空间和时间。

伪代码:

table = {}
for each element x_i in x in ascending order of i:
  if x_i is not in table:
    table[x_i] = i
best_pair = (-1,-1)
for each element y_j in y:
  if y_j in table:
    if (table[y_j],j) is "better" than best_pair:
      best_pair = (table[y_j], j)
return best_pair

我很确定它与element distinctness problem 过于相似,无法在不使用散列的情况下克服 Omega(nlogn) 边界,但没有想到任何证据。

【讨论】:

  • 这就是我要找的名字,谢谢!你的算法和 templatetypedef 都解决了这个问题,但是当你有一个无限的字母大小(例如你有一个字符串序列!)时,你的解决这个问题更普遍。
【解决方案2】:

一个选项是构建一个大小为 |Σ| 的表,其中 Σ 是您的字母表,它将每个符号与其在字符串 x 中占据的第一个位置相关联。然后,您可以遍历 x,并为每个字符记录该字符在表中 x 中的第一个位置。然后,您可以对字符串 y 进行传递,对于 y 的每个字符,请查阅表格以查找该字符第一次出现在字符串 x 中的时间。你没有在你的问题中提到你如何定义“最小”对(字典顺序?最小化 i + j?别的东西?),但你应该能够生成所有可能的对,然后取其中的最小值线性时间。

总的来说,这需要时间 O(n + |Σ|) 和使用空间 O(|Σ|),所以如果你的字母表不是太大,这很快。如果您的字母表很大,只需使用一个哈希表,这最终会是 O(n) 时间和 O(n) 空间。

【讨论】:

  • 我在最新版本中对 (i, j) 对的排序不明确,但最初我对任何通用指标都感兴趣。我喜欢你的答案,因为它处理小字母表的情况,它与阿米特更一般的答案非常相似,可以处理任意字母大小的序列。
【解决方案3】:

O(n+m) 算法:

  • 从 i = 0 和 j = 0 开始
  • 如果 x[i]
  • 如果 x[i] > y[j] j++
  • 如果 x[i] == y[j] => 你找到了

显然,您还需要检查数组边界。

【讨论】:

  • 数组未排序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-27
相关资源
最近更新 更多