​LeetCode刷题实战399:除法求值

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 除法求值,我们先来看题面:

https://leetcode-cn.com/problems/evaluate-division/

You are given an array of variable pairs equations and an array of real numbers values, where equations[i] = [Ai, Bi] and values[i] represent the equation Ai / Bi = values[i]. Each Ai or Bi is a string that represents a single variable.

You are also given some queries, where queries[j] = [Cj, Dj] represents the jth query where you must find the answer for Cj / Dj = ?.

Return the answers to all queries. If a single answer cannot be determined, return -1.0.

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

给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] = [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi = values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。

另有一些以数组 queries 表示的问题,其中 queries[j] = [Cj, Dj] 表示第 j 个问题,请你根据已知条件找出 Cj / Dj = ? 的结果作为答案。

返回 所有问题的答案 。如果存在某个无法确定的答案,则用 -1.0 替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串,也需要用 -1.0 替代这个答案。

注意:输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。

示例

7c42d443351db5fa9668a360909a6e51.png

解题

https://blog.csdn.net/qq_41231926/article/details/90904134

思路:图的深度优先遍历

本题是一题经典的图论算法,这里的除法运算可以看成是连接两个节点的一条有向边,那么计算结果存在的条件是什么呢?

(1)两个字符串在equations中都出现过。

(2)这两个字符串在equations中存在联系,即同属于一个连通分量。

首先,利用一个Map将字符串与数字编号一一对应起来。

对于图的深度优先遍历,我们选择用一个邻接矩阵graph来存储图的边权值,同时每一次求两点间的距离都初始化一个visited数组来标记哪些节点已经被遍历过。深度优先遍历过程中,求解距离用的不应该是加法,而应该是乘法。

时间复杂度是O(n * m),其中n为queries中的查询数,而m指的是由equations生成的节点数。空间复杂度是O(m ^ 2)。

public class Solution {
 
    private Map<String, Integer> stringToInteger = new HashMap<>();
 
    private int index = 0;
 
    private double[][] graph;
 
    private boolean[] visited;
 
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        for (List<String> list : equations) {
            for (String string : list) {
                if (!stringToInteger.containsKey(string)) {
                    stringToInteger.put(string, index++);
                }
            }
        }
        graph = new double[index][index];
        for (int i = 0; i < equations.size(); i++) {
            List<String> list = equations.get(i);
            String string0 = list.get(0), string1 = list.get(1);
            int index1 = stringToInteger.get(string0), index2 = stringToInteger.get(string1);
            graph[index1][index2] = values[i];
            graph[index2][index1] = 1.0 / values[i];
        }
        double[] result = new double[queries.size()];
        Arrays.fill(result, -1.0);
        for (int i = 0; i < result.length; i++) {
            List<String> list = queries.get(i);
            String string0 = list.get(0), string1 = list.get(1);
            if (stringToInteger.containsKey(string0) && stringToInteger.containsKey(string1)) {
                if (string0.equals(string1)) {
                    result[i] = 1.0;
                } else {
                    int index1 = stringToInteger.get(string0), index2 = stringToInteger.get(string1);
                    visited = new boolean[index];
                    double len = 1.0;
                    dfs(index1, index2, len, result, i);
                }
            }
        }
        return result;
    }
 
    private void dfs(int begin, int end, double len, double[] result, int k) {
        if (graph[begin][end] == 0) {
            visited[begin] = true;
            for (int i = 0; i < index; i++) {
                if (!visited[i] && graph[begin][i] != 0) {
                    dfs(i, end, len * graph[begin][i], result, k);
                }
            }
        } else {
            result[k] = len * graph[begin][end];
        }
    }
 
}

好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。

上期推文:

LeetCode1-380题汇总,希望对你有点帮助!

LeetCode刷题实战381:O(1) 时间插入、删除和获取随机元素

LeetCode刷题实战382:链表随机节点

LeetCode刷题实战383:赎金信

LeetCode刷题实战384:打乱数组

LeetCode刷题实战385:迷你语法分析器

LeetCode刷题实战386:字典序排数

LeetCode刷题实战387:字符串中的第一个唯一字符

LeetCode刷题实战388:文件的最长绝对路径

LeetCode刷题实战389:找不同

LeetCode刷题实战390:消除游戏

LeetCode刷题实战391:完美矩形

LeetCode刷题实战392:判断子序列

LeetCode刷题实战393:UTF-8 编码验证

LeetCode刷题实战394:字符串解码

LeetCode刷题实战395:至少有 K 个重复字符的最长子串

LeetCode刷题实战396:旋转函数

LeetCode刷题实战397:整数替换

LeetCode刷题实战398:随机数索引

631e2cfc492827251b94f9297b83511e.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值