【LeetCode】399. 除法求值 並查集

在這裏插入圖片描述
在這裏插入圖片描述

這道題目的解法是帶權值的並查集。

並查集

可以看這篇文章的講解:

https://blog.csdn.net/niushuai666/article/details/6662911

並查集由一個整數型的數組和兩個函數構成。數組pre[]記錄了每個點的前導點是什麼,函數find是查找,join是合併

解題思路:建立兩個map,一個map存儲上一級結點。一個map存儲比值。首先不斷構建查並集結構。如果兩者根節點不一致,進行合併。然後輸出最終的結果即可。

在這裏插入圖片描述

public class Solution {
    HashMap<String, String> path = new HashMap<>();  // key是當前結點,value是父結點
    HashMap<String, Double> value = new HashMap<>();  // key是當前結點,value是父結點/此結點

    public double[] calcEquation(List<List<String>> equations,
                                 double[] values,
                                 List<List<String>> queries) {
        // 這道題目用並查集的方式來求解。
        // 帶權值的並查集。
        for (int i = 0; i < values.length; i++) {// 遍歷被除數,除數,商。
            String parent = equations.get(i).get(0);
            String child = equations.get(i).get(1);
            double divide = values[i];
            // 首先保證 map中有這兩個結點。
            if (!path.containsKey(parent)) {
                path.put(parent, parent);
                value.put(parent, 1.0);
            }
            if (!path.containsKey(child)) {
                path.put(child, child);
                value.put(child, 1.0);
            }
            String root1 = findRoot(parent);// 找到了parent的根節點
            String root2 = findRoot(child);// 找到了,child的根節點
            // 分成兩種情況,兩者根節點一致;兩者根節點不一致。
            // 一致的話,不用管了。不一致的話,進行根節點的合併。
            if(!root1.equals(root2)){
                path.put(root2,root1);
                value.put(root2,divide*value.get(parent)/value.get(child));
            }
        }
        // 現在已經將數據按照並查集的格式存儲好了
        double[] res = new double[queries.size()];
        for (int i = 0; i< queries.size(); i++) {
            List<String> query = queries.get(i);
            String s1 = query.get(0);
            String s2 = query.get(1);
            if(!(path.containsKey(s1)&&path.containsKey(s2))){
                res[i] = -1.0;
                continue;
            }
            // 說明 兩者都包括
            String root1 = findRoot(s1);
            String root2 = findRoot(s2);
            if(!root1.equals(root2)){
                res[i] = -1.0;
                continue;
            }
            // 說明 兩者的根結點一致。
            res[i] = value.get(s2)/value.get(s1);
        }
        return res;
    }

    private String findRoot(String str) {
        // 這個方法能夠找到,str的根結點。
        // 並且最終將此結點直接與根節點相連。(設置其value值)
        String save = str;
        double divide = 1.0;
        if (path.get(str).equals(str)) {
            return str;
        }
        // 說明root不是自己。
        while (!path.get(str).equals(str)) {
            // 如果str的父結點 不等於 str
            divide *= value.get(str);
            str = path.get(str);
        }
        divide *= value.get(str);
        path.put(save, str);
        value.put(save, divide);
        return str;
    }


}

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