Leetcode 990. 等式方程的可滿足性【並查集】

問題描述

給定一個由表示變量之間關係的字符串方程組成的數組,每個字符串方程 equations[i] 的長度爲 4,並採用兩種不同的形式之一:"a==b""a!=b"。在這裏,a 和 b 是小寫字母(不一定不同),表示單字母變量名。

只有當可以將整數分配給變量名,以便滿足所有給定的方程時才返回 true,否則返回 false

示例 1:

輸入:[“a==b”,“b!=a”]
輸出:false
解釋:如果我們指定,a = 1 且 b = 1,那麼可以滿足第一個方程,但無法滿足第二個方程。沒有辦法分配變量同時滿足這兩個方程。

解題報告

並查集主要用於解決一些元素分組的問題。它管理一系列不相交的集合,並支持兩種操作

  • 合併(Union):把兩個不相交的集合合併爲一個集合
  • 查詢(Find):查詢兩個元素是否在同一集合中。2^{2}

算法步驟:

  • 將所有具有相等關係的字母進行 merge
  • 然後遍歷所有不相等的關係,如果發現不相等的兩個字母在同一個集合中,那麼直接返回 false

同時使用了 路徑壓縮按秩合併 的優化策略。

實現代碼

class Solution{
    public:
        unordered_map<int, int>parent, cnt; 
        int find(int index){
            return parent[index]==index?index:parent[index]=find(parent[index]);
        }
        void merge(int a, int b){
            a=find(a);
            b=find(b);
            if(a==b) return;
            // 按秩合併,爲了使得合併後的子樹高度儘量低,
            // 需要把高度曉得那棵子樹接在高度高的那個樹下
            if(cnt[a]<cnt[b]){
                parent[a]=b;
                cnt[b]+=cnt[a];
            }
            else{
                parent[b]=a;
                cnt[a]+=cnt[b];
            }
        }
        bool equationsPossible(vector<string>&equations){
            for(int i=0;i<26;i++){
                parent[i]=i;
                cnt[i]=1;
            }
            
            for (const string& str: equations) {
                if (str[1] == '=') {
                    int index1 = str[0] - 'a';
                    int index2 = str[3] - 'a';
                    merge(index1, index2);
                }
            }
            for (const string& str: equations) {
                if (str[1] == '!') {
                    int index1 = str[0] - 'a';
                    int index2 = str[3] - 'a';
                    if (find(index1) == find(index2)) {
                        return false;
                    }
                }
            }
        return true;
        }
};

參考資料

[1] Leetcode 990. 等式方程的可滿足性
[2] 算法學習筆記(1) : 並查集
[3]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章