[Leetcode] 399.部門の評価


タイトル説明

[Leetcode] 399.部門の評価

方程式A / B = kが与えられた場合、AとBは文字列を表す変数であり、kは浮動小数点数です。既知の方程式に従って問題を解決し、計算結果を返します。結果が存在しない場合は、-1.0を返します。

例:

给定 a / b = 2.0, b / c = 3.0
问题: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? 
返回 [6.0, 0.5, -1.0, 1.0, -1.0 ]

入力は次のとおりです。

  • vector <pair <string、string >>方程式、
  • vector <double>&値、
  • vector <pair <string、string >>クエリ(方程式、方程式の結果、問題の方程式)、

その中で、equations.size()== values.size()、つまり、方程式の長さは方程式の結果の長さと等しく(プログラムは結果と1対1で対応します)、結果の値は正です。以上が方程式の説明です。vector <double>型を返します。

上記の例に基づいて、次のように入力します。

equations(方程式) = [ ["a", "b"], ["b", "c"] ],
values(方程式结果) = [2.0, 3.0],
queries(问题方程式) = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. 

入力は常に有効です。除算演算で除数0はなく、矛盾する結果はないと想定できます。

最初の答え

アイデア
重み付けされたエッジを持つユニオン検索セット作成するには、方程式ごとに2つの状況があります。

  1. 接続されているかどうかを問い合わせます。接続されていない場合、答えは-1.0です。
  2. 接続されている場合は、それを根で割った結果を求め、その結果に基づいて方程式を計算します。

たとえば、タイトルの例の場合:

  1. ユニオン検索セットを構成します:a-> b-> c。ここで、a-> bのエッジの重みは2.0で、b-> cのエッジの重みは3.0です。
  2. 例としてb / aの計算を取り上げ、ルートノードをブリッジとして取り、b / aの値を計算します
    。1.最初にb / rootを計算します。ここで、rootはc、次にb / c = 3.0
    2.次に、a / rootを計算します。ここで、根はcであり、a / c = a / b * b / c = 2.0 * 3.0 = 6.0
    3.最後に方程式の結果を計算します:b / a = 3.0 / 6.0 = 0.5

注意:

  • 上記の分析によれば、結合検索セットはパス圧縮やランク最適化などの操作を実行できず、結合検索セットの構造は方程式の構造と同じでなければならず、そうでなければ計算結果が間違っているはずです。
  • 実際、構造も異なる場合がありますが、構造が変化するとエッジの方向も変化するため、エッジの重みの更新には注意が必要です。

テストケース:
[[“ a”、“ b”]、[“ b”、“ c”]]
[2.0,3.0]
[[“ a”、“ c”]、[“ b”、“ a”]、 [“ a”、“ e”]、[“ a”、“ a”]、[“ x”、“ x”]]
[[“ a”、“ b”]、[“ b”、“ c”] 、[“ bc”、“ cd”]]
[1.5,2.5,5.0]
[[“ a”、“ c”]、[“ c”、“ b”]、[“ bc”、“ cd”]、[ 「cd」、「bc」]]

コード:

class Solution {
    
    
public:
    int count;
    unordered_map<string, string> parents; // 存储当前结点的父母
    unordered_map<string, double> weights; // 存储 当前结点值/父母值 的结果

    // 返回root以及从a/root的值
    pair<string ,double> MyFind(string a){
    
    
        if(parents.find(a) == parents.end())
            return {
    
    "", -1.0};
        double result = 1.0;
        while(a != parents[a]){
    
    
            result *= weights[a]; // result *= a/parent;
            // 路径压缩后还需要更新weights,这里偷懒就不路径压缩了
            a = parents[a];
        }
        return {
    
    a, result}; // 返回a的根节点,和a/root的结果
    }
 
    // a_b表示a除以b的结果
    void MyUnion(string a, string b, double a_b){
    
    
        pair<string, double> p1 = MyFind(a);
        pair<string, double> p2 = MyFind(b);
        if("" == p1.first || "" == p2.first) return;
        if(p1.first == p2.first) return;
        parents[p1.first] = p2.first; 
        weights[p1.first] = 1/p1.second * a_b * p2.second; // 更新权重
        count--;
    }
    vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
    
    
        // 并
        for(int i=0; i<equations.size(); ++i){
    
    
            string a = equations[i][0];
            string b = equations[i][1];
            // 并查集初始化
            if(parents.find(a) == parents.end()){
    
    
                count++;
                parents[a] = a;
                weights[a] = 1.0;
            }
            if(parents.find(b) == parents.end()){
    
    
                count++;
                parents[b] = b;
                weights[b] = 1.0;
            }
            // 并操作
            MyUnion(a, b, values[i]);
        }

        // 查
        vector<double> result;
        for(auto &q : queries){
    
    
            string a = q[0];
            string b = q[1];
            pair<string, double> p1 = MyFind(a); // p1.second = a/p1
            pair<string, double> p2 = MyFind(b); // p2.second = b/p2
            if(p1.first != p2.first || "" == p1.first || "" == p2.first){
    
    
                result.push_back(-1.0);
            }
            else{
    
    
                result.push_back(p1.second/p2.second); // a/b = (a/p1) / (b/p2);
            }
        }
        return result;

    }
};

結果:
スクリーンショット

関連/参照リンク

おすすめ

転載: blog.csdn.net/a435262767/article/details/105438640