LeetCode 399. Evaluate Division

本文介绍了一种解决变量间关系查询的问题,通过构建图模型并使用深度优先搜索或改进的弗洛伊德算法来高效计算变量间的比率。两种方法均可处理给定的等式集合,以回答关于变量间比率的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Statement

(Source) Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.

Example:
Given a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].

The input is: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries, where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector<double>.

According to the example above:

equations = [ ["a", "b"], ["b", "c"] ],
values = [2.0, 3.0],
queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. 

The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.

Tags: Graph.

class Solution(object):
    def calcEquation(self, equations, values, queries):
        """
        :type equations: List[List[str]]
        :type values: List[float]
        :type queries: List[List[str]]
        :rtype: List[float]
        """
        # Graph.
        g = {}
        n = len(values)
        for i in xrange(n):
            A, B = equations[i]
            k = values[i]
            g.setdefault(A, {})[B] = k
            g.setdefault(B, {})[A] = 1 / k

        # Depth-first Search.
        from collections import deque


        m = len(queries)
        res = [-1.0] * m
        for i in xrange(m):
            A, B = queries[i]
            if (A not in g) or (B not in g):
                continue
            elif A == B:
                res[i] = 1
                continue
            sta = deque([A])
            explored = set([A])
            ans = 1.0
            while sta:
                top = sta[-1]
                for C in g[top]:
                    y = g[top][C]
                    if C not in explored:
                        explored.add(C)
                        sta.append(C)
                        ans *= y
                        break
                if sta[-1] == top:
                    y = sta.pop()
                    if sta:
                        x = sta[-1]
                        ans /= g[x][y]
                else:
                    if sta[-1] == B:
                        res[i] = ans
                        break
        return res

Complexity Analysis:

  • Time Complexity: O(mn) , where m is the number of variables (or equations), and n is the number of queries.
  • Space Complexity: O(mn) , where m is the number of variables (or equations), and n is the number of queries.

Solution 2 - Amazing

A variation of Floyd–Warshall, computing quotients instead of shortest paths. An equation A/B=k is like a graph edge A->B, and (A/B)(B/C)(C/D) is like the path A->B->C->D. Submitted once, accepted in 35 ms (Credits @StephanPochmann).

def calcEquation(self, equations, values, queries):
    quot = collections.defaultdict(dict)
    for (num, den), val in zip(equations, values):
        quot[num][num] = quot[den][den] = 1.0
        quot[num][den] = val
        quot[den][num] = 1 / val
    for k, i, j in itertools.permutations(quot, 3):
        if k in quot[i] and j in quot[k]:
            quot[i][j] = quot[i][k] * quot[k][j]
    return [quot[num].get(den, -1.0) for num, den in queries]

Variation without the if (submitted twice, accepted in 68 and 39 ms):

def calcEquation(self, equations, values, queries):
    quot = collections.defaultdict(dict)
    for (num, den), val in zip(equations, values):
        quot[num][num] = quot[den][den] = 1.0
        quot[num][den] = val
        quot[den][num] = 1 / val
    for k in quot:
        for i in quot[k]:
            for j in quot[k]:
                quot[i][j] = quot[i][k] * quot[k][j]
    return [quot[num].get(den, -1.0) for num, den in queries]

Could save a line with for i, j in itertools.permutations(quot[k], 2) but it’s longer and I don’t like it as much here.

Explanation (Credits @ww123):

Nice solution. This is a floyd-warshall-y solution because of the triple nested loops. However it is difficult for me to understand it following the floyd-warshall reasoning. I will share my $.02 here. Correct me if I’m wrong.

Concretely the triple loops create a complete graph. For the first node, connect every pair of its neighbors, a complete sub-graph containing the first node. then the second, then the third, …. so after the loops, all related variables will be in one big complete graph.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值