改善从排序的字符串获取字母顺序的顺序复杂度

时间:2018-09-25 02:42:18

标签: python c++ algorithm

说我有一个列表(大小为n),按某种语言按字典顺序排序的字符串(最大大小为m),由a-z组成,但不包括a, b, c...的词汇顺序。现在的主要问题是我想找到字母的顺序。因此,我将问题分为两个部分:

  1. 从列表中的字符串中查找有序的字母对。
  2. 从这些对中构造有向图作为边。对图进行拓扑排序以获取顺序。

我的问题是关于第一个的。

要做1,我做了一个O(n ^ 2m)循环:

vector<pair<char, char> > build_ordered_pairs(vector<string> words) {
    vector<pair<char, char> > ordered_pairs;
    for(int i=0;i<n;i++) {
        for(int j=i+1;j<n;j++) {
            k = 0;
            while(k < words[i].size() && k < words[j].size() && words[i][k] == words[j][k])
                k++;
            if(k < words[i].size() && k < words[j].size())
                ordered_pairs.push_back(make_pair(words[i][k], words[j][k]));
        }
    }
    return ordered_pairs;
}

为了改善这一点,我们可以将字符串放入trie,然后从trie的每个级别获取对。但这又将是n的二次方。我们可以做得更好,例如nlogn还是n?

我们可能一次又一次得到相同的对。因此,我们可以检查是否不需要特定的一对,因此可以在同时构建有向图时跳过它。预先感谢。

示例输入输出对:

words = {"baa", "abcd", "abca", "cab", "cad"}
required = {'b', 'd', 'a', 'c'}

P.S:也可以标记为python,因为这两种解决方案/建议都对我有用。

2 个答案:

答案 0 :(得分:3)

您正在检查的字符串对数量超出了您的需要。您只需要检查连续的字符串对,而不是所有的字符串对。 0-1、1-2和2-3比较暗示通过比较字符串0和3所获得的信息,并且拓扑排序可以为您处理。拓扑排序也应该更快运行,并且输入中的多余边也应更少。

答案 1 :(得分:1)

曾经从事实际的实现,但是@ user2357112已经解释了它的要旨。由于列表已经按照字典顺序排序,因此您可以在遍历列表时跟踪最后一个单词的第一个字母,如果与当前单词的第一个字母相同,则将当前单词的其余部分放入一个列表,直到当前单词的第一个字母与最后一个单词的不同,这时将列表传递给递归调用。该实现的平均时间复杂度将改为O(n * log(n))。

这是Python中的实现(使用collections.deque进行有效的popleft操作):

from collections import deque
def build_ordered_pairs(words):
    output = []
    if len(words) < 2:
        return output
    last_letter = None
    same_prefix = deque()
    while words:
        letter, *rest = words.popleft()
        if letter == last_letter:
            same_prefix.append(rest)
        else:
            if last_letter:
                output.append((last_letter, letter))
            output.extend(build_ordered_pairs(same_prefix))
            same_prefix = deque([rest])
        last_letter = letter
    output.extend(build_ordered_pairs(same_prefix))
    return output

这样:

words = deque(["baa", "abcd", "abca", "cab", "cad"])
print(build_ordered_pairs(words))

将输出:

[('b', 'a'), ('a', 'c'), ('d', 'a'), ('b', 'd')]

由于您已经了解拓扑排序,因此在此实施的其余部分中不再赘述。