检查两个排序的字符串在 O(log n) 时间内是不是相等

Posted

技术标签:

【中文标题】检查两个排序的字符串在 O(log n) 时间内是不是相等【英文标题】:Check if two sorted strings are equal in O(log n) time检查两个排序的字符串在 O(log n) 时间内是否相等 【发布时间】:2020-05-10 05:40:04 【问题描述】:

我需要编写一个 Python 函数,它接受两个仅包含小写字母的排序字符串(每个字符串中的字符按字母顺序递增),并检查字符串是否相等。 函数的时间复杂度需要为O(log n),其中n是每个字符串的长度。

如果不将第一个字符串中的每个字符与第二个字符串的并行字符进行比较,我无法弄清楚如何检查它。

【问题讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:

事实上,在最坏的情况下,这在 O(log n) 时间内是可能的,因为字符串是由一个恒定大小的字母表组成的。

您可以对每个字符串执行 26 次二进制搜索,以找到每个字母最左侧出现的位置。如果字符串相等,那么所有 26 次二分搜索都会给出相同的结果;要么该字母在两个字符串中都不存在,要么它最左边的出现在两个字符串中相同。

相反,如果所有的二分搜索都给出相同的结果,那么字符串必须相等,因为 (1) 字母表是固定的,(2) 最左边出现的索引决定了每个字母在字符串,以及 (3) 对字符串进行排序,因此字母频率唯一确定字符串。

我在这里假设字符串具有相同的长度。如果他们可能没有,那么首先检查并返回False 如果长度不同。获取字符串的长度需要 O(1) 时间。


正如@wim 在 cmets 中指出的那样,这个解决方案不能推广到数字列表;它只适用于字符串。当您遇到涉及字符串的算法问题时,字母大小通常是一个常数,并且通常可以利用这一事实来实现比其他方法更好的时间复杂度。

【讨论】:

根据此图,对于大小小于 450 的字符串,这种方法比简单迭代要慢:desmos.com/calculator/7tmzw8yspg 对我来说,这是一个完美的例子,说明了为什么我们应该只使用 big-o 符号作为指导。快速 O(n) 击败慢速 O(logn) 甚至是快速 O(n^2) 击败慢速 O(n) 的情况并不少见。 @mypetlion 感谢您进行分析。二进制搜索不会遍历字符串,因为这会降低 O(n) 性能;只需继续二进制搜索即可找到最左边的出现。我的算法稍微优化的版本将比较索引 0 处的字符,然后如果它们相等,则搜索大于它的字符的第一次出现,依此类推;每个字符串最多可以进行 25 次二进制搜索,如果字符串不使用每个字母,则更少。如果你愿意,你也可以回退到 n 这个算法捕捉到了基本的洞察力。更实用的方法是将字符串递归地分成两半,但当子字符串以相同字符开头和结尾时短路。 我尝试了最简单的版本all(bisect(s, c) == bisect(t, c) for c in string.ascii_lowercase),它在几十万个字符的字符串中赶上了s == t

以上是关于检查两个排序的字符串在 O(log n) 时间内是不是相等的主要内容,如果未能解决你的问题,请参考以下文章

字谜排序版本与计数字符版本

几种能在O(n*log(n))时间排序

几种排序算法

常见算法

常用的排序算法的时间复杂度和空间复杂度

常用的排序算法的时间复杂度和空间复杂度