LeetCode: 399. Evaluate Division

LeetCode: 399. Evaluate Division

題目比較好理解哈,定義兩個string的商,然後發起一系列查詢,需要輸出可以推出的商,不能得出的商爲-1.0。這題目有幾點要注意的:
- x/x=-1.0雖然我們知道就算不知道x的值,但是題目其實已經確保了x不爲0,那麼實際上答案應該是1.0,但題目的例程把它定義爲-1.0。當然是題意最大啦。
- 不考慮無效輸入,同時會保證分母不是0

既然這個題目的分類是Graphs,自然可以用有向圖來解決問題了。每個string是點的值(唯一標識),有向邊的值表示a/b,其中a是出點,b是入點。

很自然的一個思路是:
- 建圖:根據每個輸入得到a/b=k和b/a=1/k兩條有向邊,時間複雜度O(n)
- 遍歷:遍歷搜索是否有解,時間複雜度O(n)(最壞情況歷遍所有的點才能得到解)

代碼

遍歷就少不了DFS還是BFS了,DFS形式上簡單,但是要注意停止條件和難以控制遞歸層數。BFS則寫起來複雜些,而且需要額外的空間來存儲壓棧但尚未處理的點和中間的搜索值(來加快在大查詢量的情況下的搜索速度,避免重複計算一些對的商,這個思想可以參考斐波那契數列的空間換時間思想)。

下面是用DFS寫的。爲了方便也爲了快速,用unorder_map來做graphs的結構,事實上可以算是一種鄰接表的思想,但是搜索插入刪除的複雜度都是O(1)。要注意的是:visited的設置,避免重複搜索。

unordered_map<string,vector<pair<string,double>>> graphs;
unordered_set<string> visited;
double thisOne;

void dfs (string pstart, string pend, double val)
{
    if (pstart == pend)
    {
        thisOne = val;
        return;
    }

    vector<pair<string, double>> temps = graphs[pstart];

    for (auto tmp : temps)
    {
        if (visited.find(tmp.first) == visited.end())
        {
            visited.insert(tmp.first);
            dfs(tmp.first, pend, val * tmp.second);
        }
        if (thisOne)
            break;
    }
}
vector<double> calcEquation(vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries)
{
    vector<double> ans(queries.size());
    //bulid the map
    for(int i=0; i<equations.size(); i++)
    {
        graphs[equations[i].first].push_back(make_pair(equations[i].second,values[i]));
        graphs[equations[i].second].push_back(make_pair(equations[i].first,1.0 / values[i]));
    }

    //query
    for(int i = 0; i<queries.size(); i++)
    {
        visited.clear();
        thisOne =0;
        string pstart = queries[i].first;
        string pend = queries[i].second;

        if(graphs.find(pstart) ==graphs.end() || graphs.find(pend) == graphs.end())
        {
            ans[i]=-1.0;
        }
        else
        {
            visited.insert(pstart);
            dfs(pstart,pend, 1.0);
            if (thisOne)
                ans[i] = thisOne;
            else
                ans[i] = -1;
        }
    }
}

BFS感覺會快些,就是每次搜索完把新的結果放進graphs裏面,這樣後面搜索就快了。不過貌似testcase都不大,所以這道題很多人用dfs0ms的。

拓展

其實有種更加快的,是用並查集。理解+基本實現參考,簡單說就是用連通性把所有連通子集都作爲一個並查集。可以把複雜度從O(n)降到O(logn)。

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