LeetCode 399 Evaluate Division

文章目录

题意

给出多个形如 a/b=k 的式子以及询问 a/b=?,要求对回答每个询问的结果,若从式子推导不出询问的答案,则返回-1。其中 a, b 为任意字符串,k 为实数。例如:

式子: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 

思路

不难想到的是将除法变成乘法的形式,例如 a/b=2 可以变为 a=2b,那么通过将每个字符串表示为其它字符串的倍数,就能得到任意两个之间的倍数关系。例如对于 a/b=2, c/b=3, e/c=3,可以得到 a=2b, c=3b, e=9b 那么 a/b, a/c, b/c, b/e, c/e 就都能得到。进一步,这种关系可以通过并查集这种数据结构实现,以类似于树的关系将 e 表示成根节点 b 的倍数,即可判断任意两个之间的关系。与并查集类似,在建立关系树的时候要考虑两个子树之间的合并关系:合并子树的。步骤如下:

  1. 构造数据结构以表示a=kb这种关系
  2. 考虑每一个等式 a/b=k
    1. a, b 都不在任一子树中,以 b 为根建立子树
    2. a, b 其中一个在某个子树中, 找到子树的根,将不在子树上的加入子树
    3. a, b 在不同的子树上,找到两颗子树的根,合并子树
  3. 对每个询问,通过与根的倍数关系得出结果

代码


struct relation {
    int who;
    double times;
    relation(int w, double t) {
        who = w, times = t;
    }
};
class Solution {
private:
    map<string, int> ids;
    vector<relation> fathers;
    int idtot = 0;
public:
    vector<double> calcEquation(vector<vector<string>> &equations, vector<double> &values, vector<vector<string>> &queries) {
        for (int i = 0; i < equations.size(); i++) {
            setFather(equations[i], values[i]);
        }
        vector<double> resvec;
        for (auto &&vec : queries) {
            double ret = queryK(vec[0], vec[1]);
            resvec.push_back(ret);
        }
        return resvec;
    }
    relation findFaa(int id) {
        relation ret = fathers[id];
        if (ret.who == id)
            return ret;
        relation tmp = findFaa(ret.who);
        ret.who = tmp.who;
        ret.times *= tmp.times;
        return ret;
    }
    void setFather(vector<string> equation, double value) {
        string a = equation[0], b = equation[1];
        if (ids.find(a) == ids.end() && ids.find(b) == ids.end()) {
            int aid = idtot++;
            int bid = idtot++;
            ids[a] = aid;
            ids[b] = bid;
            fathers.push_back(relation(bid, value));
            fathers.push_back(relation(bid, 1));
        } else if (ids.find(a) == ids.end()) {
            int aid = idtot++;
            int bid = ids[b];
            ids[a] = aid;
            relation bfa = findFaa(bid);
            fathers.push_back(relation(bfa.who, value * bfa.times));
        } else if (ids.find(b) == ids.end()) {
            int aid = ids[a];
            int bid = idtot++;
            ids[b] = bid;
            relation afa = findFaa(aid);
            fathers.push_back(relation(afa.who, (1.0 / value) * afa.times));
        } else {
            int aid = ids[a], bid = ids[b];
            relation afa = findFaa(aid), bfa = findFaa(bid);
            if (afa.who != bfa.who) {
                fathers[afa.who].times = bfa.times * value / afa.times;
                fathers[afa.who].who = bfa.who;
            }
        }
    }
    double queryK(string a, string b) {
        if (ids.find(a) == ids.end() || ids.find(b) == ids.end())
            return -1;
        int aid = ids[a], bid = ids[b];
        relation afa = findFaa(aid), bfa = findFaa(bid);
        if (afa.who != bfa.who)
            return -1;
        return afa.times / bfa.times;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章