联盟发现leetcode问题超出时间限制

时间:2018-09-05 07:12:42

标签: c++ algorithm graph union-find

我正在leetcode https://leetcode.com/problems/sentence-similarity-ii/description/上解决此问题,其中涉及实现联合查找算法,以找出两个句子是否相似,或者没有给出代表相似单词的对的列表。我实现了分级联合查找,在其中跟踪每个子集的大小,并将较小的子树连接到较大的子树,但是由于某些原因,代码仍然超出了时间限制。有人可以指出我做错了什么吗?如何进一步优化。我看到其他接受的解决方案正在使用相同排名的联合查找算法。

代码如下:

    string root(map<string, string> dict, string element) {
    if(dict[element] == element)
        return element;
    return root(dict, dict[element]);
}
bool areSentencesSimilarTwo(vector<string>& words1, vector<string>& words2, vector<pair<string, string>> pairs) {
    if(words1.size() != words2.size()) return false;
    std::map<string, string> dict;
    std::map<string, int> sizes;
    for(auto pair: pairs) {
        if(dict.find(pair.first) == dict.end()) {
            dict[pair.first] = pair.first;
            sizes[pair.first] = 1;
        }
        if(dict.find(pair.second) == dict.end()) {
            dict[pair.second] = pair.second;
            sizes[pair.second] = 1;
        }

        auto firstRoot = root(dict, pair.first);
        auto secondRoot = root(dict, pair.second);
        if(sizes[firstRoot] < sizes[secondRoot]) {
            dict[firstRoot] = secondRoot;
            sizes[firstRoot] += sizes[secondRoot];
        }
        else {
            dict[secondRoot] = firstRoot;
            sizes[secondRoot] += sizes[firstRoot];
        }
    }


    for(int i = 0; i < words1.size(); i++) {
        if(words1[i] == words2[i]) {
            continue;  
        }
        else if(root(dict, words1[i]) != root(dict, words2[i])) {
            return false;
        }
    }
    return true;
}

谢谢!

1 个答案:

答案 0 :(得分:0)

关于复杂性,您的工会发现被打破了。请阅读Wikipedia: Disjoint-set data structure

要使联合查找具有接近O(1)的复杂度,它必须采用路径压缩。为此,您的root方法必须:

  1. 通过引用获取dict,以便它可以对其进行修改。
  2. 对路径上的所有元素进行路径压缩,使其指向根。

不进行压缩,root()的复杂度为O(log N),可以。但是为此,您必须对其进行修复,以使root()通过引用而不是通过值获得dict。按值传递dict的成本为O(N)。

dictstd::map的事实使任何查询成本为O(log N),而不是O(1)。 std::unordered_map的成本为O(1),但实际上对于N <1000,std::map的速度更快。另外,即使使用std::unordered_map,对字符串进行散列也要花费O(len(str))。

如果数据量很大,并且性能仍然很慢,则可以使用索引到pairs而不是字符串中的索引,然后对索引运行到vector<int>的联合查找中来。这很容易出错,因为您必须正确处理重复的字符串。