【问题标题】:Determining if a sequence T is a sorting of a sequence S in O(n) time确定序列 T 是否是序列 S 在 O(n) 时间内的排序
【发布时间】:2012-04-01 21:04:51
【问题描述】:

我知道可以很容易地确定一个序列是否在 O(n) 时间内排序。但是,我们如何保证某个序列 T 确实是在 O(n) 时间内对序列 S 中的元素进行排序呢?

也就是说,有人可能有一个算法输出一些序列 T 确实是有序的,但可能不包含序列 S 中的任何元素,那么我们如何检查 T 确实是 S 在 O( n) 时间?

【问题讨论】:

  • 如果你的意思是 O() 分析,它在 N 中是渐近的,那么你的问题没有 O(n) 解决方案。
  • 多年过去了,没有答案能够(检查和?)利用 T 被排序。

标签: algorithm sorting big-o sequence


【解决方案1】:
  1. 获取L的长度S
  2. 还要检查T 的长度。如果它们不同,您就完成了!
  3. Hs 成为一个哈希映射,其中包含2L 之类的S 中所有元素的桶。
  4. Ht 成为T 中所有元素的哈希映射(同样,使用2L 存储桶)。
  5. 对于T 中的每个元素,检查它是否存在于Hs 中。
  6. 对于S 中的每个元素,检查它是否存在于Ht 中。

如果每个序列中的元素都是唯一的,这将起作用。请参阅 wcdolphin 的回答,了解使其适用于非唯一序列所需的小改动。

我没有考虑内存消耗。创建两个大小为每个序列两倍的哈希图可能会很昂贵。这是速度和内存之间通常的权衡。

【讨论】:

  • 请注意,它应该是直方图map:element->int,以确保您在处理重复元素的同时仍然获得O(n)。除此之外 - 不错的解决方案。
  • -1:哈希映射不是魔术,也不是 O(1)。哈希映射与它所采用的冲突处理具有相同的 O() 复杂度。如果哈希映射使用链接,则构建它是 O(n^2)。如果哈希映射对于每个 bin 的溢出都有一个二叉树,则为 O(log N)。这就是最近的 tomcat DoS POST 漏洞背后的问题。在今天的大学里,Java“知识”作为 CS 教育被分发,许多学生被错误地认为可以像你描述的那样使用散列图——但这是错误的。您必须考虑如果发生哈希冲突会发生什么。
  • @HeathHunnicutt:你可能忘记阅读它们的最后一章了,k 不是固定不变的。负载平衡通常是~1/2-1/4,意思是2n < k < 4n,它会衰减回一个常数。 Rehashin 是 O(n) - 但在 O(n) OPS 之后完成,返回到 O(1) 按 OP 摊销
  • Heath,你为什么假设 hashmap 是满的?有谁会创建一个桶太少的哈希图?如果您指出几乎每个键或类似的东西都存在(非常不可能的)散列冲突场景,我会更理解您的抱怨,但是如果具有良好的散列函数和足够大的散列图,键冲突应该不太可能发生。
  • 我认为您还应该考虑每个元素的计数。例如,对于 A = [1, 1, 2] 和 B = [1, 2, 2],您的解决方案将回答“是”,但答案应该是“否”。
【解决方案2】:

虽然埃米尔的回答很好,但你可以做得更好。

从根本上说,为了使 T 成为 S 的重新排序,它必须包含所有相同的元素。也就是说,对于 T 或 S 中的每个元素,它们必须出现相同的次数。因此,我们将:

创建 S 中所有元素的哈希表,从“元素”映射到出现次数。

遍历 T 中的每个元素,减少当前元素出现的次数。

如果出现次数为零,则将其从哈希中删除。

如果当前元素不在散列中,则T不是S的重新排序。

【讨论】:

  • @HeathHunnicutt 你所说的“神奇的哈希映射”是什么意思?这是一个可以手工编写的标准哈希表,它所需要的只是元素是可哈希的。你能详细说明一下吗?
  • 编辑:(好吧,不允许编辑评论,但无论如何)。关于哈希表的插入复杂性的要点!虽然我认为你可能对这个简单的问题有点过分了,但它肯定会鼓励我总是三思而后行,尤其是哈希表的渐近行为。
  • 当可能存在非唯一元素时,这是一个很好的解决方案。我已经更新了我的答案来参考你:-) 它在内存消耗方面也好一点,因为它只使用一个哈希图。不错!
【解决方案3】:

创建两个序列的哈希图。使用字符作为键,字符的计数作为值。如果尚未添加字符,则将其计数为 1。如果已添加字符,则将其计数增加 1。

验证对于输入序列中的每个字符,已排序序列的哈希映射包含该字符作为键并且具有与值相同的计数。

【讨论】:

  • 嗯?这是一个相当随机的投票。哈希映射用于 O(1) 查找时间,它不是“魔术”,该算法应该在 O(n) 中工作。你能解释一下你的反对意见吗?
  • 上面已经解释过了。 O() 是渐近测度。哈希映射在评估 O() 复杂度时会转向其链接策略,因为当 N 很大时它们是满的。如果您允许哈希映射调整大小,那么调整大小也是 O(N)。
  • Hashmap 没有 O(1) 查找时间。 Hashmap 的查找时间为 O(1/k * p(N)),其中 p(N) 是链接(bin 溢出)策略,1/k 是从 O() 表示法中消失的常数因子。散列图具有 N 无穷大。
  • @HeathHunnicutt:因为通常2n < k < 4np(n) 是线性的,它会衰减回O(1) [再次,平均情况下,摊销分析]
  • @amit - N 渐近,你知道那是什么意思吗?您关于 2n k 在 O() 下,否则不是 O(),是 Theta()。
【解决方案4】:

我认为这是一个 O(n^2) 问题,因为:

  1. 假设您用于存储元素的数据结构是一个链表,用于删除元素的最小操作
  2. 您将为 T 的每个元素执行 S.contains(element of T),并检查它们的大小是否相同。
  3. 您不能假设 s 是有序的,因此需要对每个元素进行逐个元素的比较。
  4. 最坏的情况是如果 S 是 T 的倒数
  5. 这意味着对于 T 的元素 (0+x),如果删除每个成功的元素,您将进行 (n-x) 次比较。
  6. 这会导致 (n*(n+1))/2 次操作,即 O(n^2)

可能还有其他更聪明的算法

【讨论】:

  • 这不是真正的 O(N^2)。您可以在 O(N log N) 中对第二个列表进行排序,然后在 O(N) 中比较两者。所以这是一个 O(N log N) 问题。您还可以对第二个序列的每个元素的排序序列进行二分搜索(O log N),但是您必须小心计算相同数量的重复项 - 可能将排序中的每个匹配项替换为诸如 - 1,那么这是破坏性的。仍然是 O(N log N)。
猜你喜欢
  • 2013-11-01
  • 1970-01-01
  • 2011-05-08
  • 2020-06-06
  • 1970-01-01
  • 2020-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多