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)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值