Leetcode 每日一题:Evaluate Division

news2024/11/13 9:39:42

写在前面

今天依旧是一道来自图论的题目,而今天这道题目的难度也是相对于前面分享过的题目中难度最大的一种。题主在第一次做这道题的时候根本没有反应过来这道题目可以转化为 图 来解决。而这道题目将一个 二维数组的乘除 运算转化为 图论 的过程需要一定的数学思维思考,今天就让我们一起来看看这道题怎么个事儿吧~~

题目介绍:

题目信息:

  • 题目链接:https://leetcode.com/problems/evaluate-division/description/
  • 题目类型: Array,Graph, DFS,Union-Find (没错可以用 uf,但是今天暂时不分享这种做法)
  • 题目难度:Medium (但其实真的可以算是 hard,在面试中如果第一次碰到这个题就自求多福啦 ~~)
  • 题目来源:Google 高频面试题

题目问题:

  • 给定一个数组 pairs(equations)每一个 pair 的第一个是除数,第二个是被除数,均由 string 变量名指代)
  • 给定一个数组(values),每一个位置的 double 值对应上一数组 pairs 的相除结果
  • 给定一个数组 pairs(queries),要求输出每一个 pair 的第一个数 / 第二个数的结果,依次按序输出
  • 如果无法计算,则结果为 -1.0
  • 举例:

题目想法:

这道题的难点在于,怎么样将一个看似与图论无关的问题转化为 图论问题,或者说,在我们刚拿到这道题的时候,我们是怎么样去思考,从而将一个看似非常独立的题目转化为我们熟悉的解题结构中呢?

我们首先观察给定的题目特性,假设我们拥有 a/b,b/c 和他们对应的值,那我们是怎么得到 a/c 的值的呢:

a/c = a/b * b/c where a/b and b/c are given known value

我们可以发现 a/c 其实就是 a/b 和 b/c 以乘法链接在一起,展现出来的样子相当于先从 a -> b, 再从 b -> c, 诶,是不是感觉好像有图论的感觉了

如果我们要知道,比如说 a/d 的值,我们就需要找到以 a 为起点,d 为重点的一个非循环路径,而在每一次路径的过程中,分子为起点,分母为终点,而每次的结果都是以乘法叠加在一起的:

a/d = a/n1 * n1/n2 * n2/n3 ..... * nk/ d

这其中的 n1, n2, n3, ..., nk 必须满足:

  • 任意 n1/n2 的值已知,即要么已经给定,要么存在于图论系统中
  • 任意 n1 != n2,一旦有循环则意味着我们不可能抵达终点

 而经过这样的转化,我们的问题就变成了,对于每一个 query 的 a/b,我们以 a 为起点,通过遍历图,找寻是否能抵达 b 这个终点。如果不能抵达返回 -1。没经过一个节点,都将当前的值乘加在总的结果上,当我们找到最后一个点时,返回所有的乘法累计结果。

总的来说:在创造这个图的时候,两点之间的连接是双向的,而这个路径上的权重则为 a/b (如果是 a -> b) 或者是 b/a (如果是 b -> a), 而在题目给定 a/b 的结果后,b/a 就是 1/(a/b))

使用 DFS 来对每一个 起点 a 和终点 b 的结果进行找寻即可

题目解法:

  • 遍历所有 “equations”“values”,对于每一个位置,分别记录下来 a -> b 和 b -> a 的adjacent 和 相应的经过需要乘算的数。
  • 遍历所有需要找寻的 “queries”:
    • 以当前 query 的起始点与末端点找寻 DFS
    • 如果通路,返回结果
    • 如果不同,返回 -1

题目代码:

class Solution {
public:
    //store the divisor and dividend's mutual path
    unordered_map<string, vector<pair<string, double>>> graph;
    set<string> visited;
    vector<double> res;
    
    //traverse the graph for a single query
    double DFS(string start, string target, double currProduct){
        //if we visited this node, then we find the loop, return:
        if(visited.find(start) != visited.end()){
            return -1.0;   //indicate that this route is not ok
        }
        
        visited.insert(start);
        
        //if we reach the end:
        if(start == target){
            return currProduct;
        }
        
         //else, go over teh map:
        vector<pair<string, double>> neighbours = graph[start];
        for(auto neighbour: neighbours){
            string new_start = neighbour.first;
            double new_product = currProduct * neighbour.second;
            double res = DFS(new_start, target, new_product);
            if(res != -1.0){
                return res;
            }
        }
        return -1.0;
    }
    
    vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
        //copy the graph down
        //for Numerator -> Denominater, it just the values at the position
        //for Denominater -> Numerator, it is the 1 / (values at the position)
        int size = values.size();
        for(int i = 0; i < size; i++){
            graph[equations[i][0]].push_back({equations[i][1], values[i]});
            graph[equations[i][1]].push_back({equations[i][0], 1.0 / values[i]});
        }
        
        //traverse the route for each queries:
        for(int i = 0; i < queries.size(); i++){
            // if one of the point not in the map, then there is no route
            if(!graph.contains(queries[i][0]) || !graph.contains(queries[i][1])){
                res.emplace_back(-1.0);
                continue;
            }
            
            // if the start and destination is the same node, then it should be a self loop
            // answer shall be one
            if(queries[i][0] == queries[i][1]){
                res.emplace_back(1.0);
                continue;
            }
            
            //traverse the graph and append the answer, clear the map everytime we did it
            double ret = DFS(queries[i][0], queries[i][1], 1.0);
            res.emplace_back(ret);
            visited.clear();
        }
        return res;
    }
};
  • Runtime: O(M*N) DFS 遍历最差是需要全部遍历 O(N) * 总共有 M 组 query O(M)
  • Space: O(N) 存储所有点的adjacent 信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2143802.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在Android上实现RTSP服务器

技术背景 在Android上实现RTSP服务器确实是一个不太常见的需求&#xff0c;因为Android平台主要是为客户端应用设计的。在一些内网场景下&#xff0c;我们更希望把安卓终端或开发板&#xff0c;作为一个IPC&#xff08;网络摄像机&#xff09;一样&#xff0c;对外提供个拉流的…

rhat Linux虚拟机桥接网络配置

本文物理机安装Windows10系统&#xff0c;虚拟机安装redhat7.7。 0、基本概念 VMware中的桥接模式&#xff08;Bridged Mode&#xff09;是一种虚拟机网络配置方式&#xff0c;它允许虚拟机直接连接到宿主机的物理网络&#xff0c;使得虚拟机能够像物理机一样访问外部网络。 在…

高颜值,实力派丨捷顺科技旗舰级人脸识别门禁、速通摆闸新品发布

9月12日&#xff0c;捷顺科技成功举办以“全新进化&#xff0c;定义非凡”为主题的2024智慧人行线上新品发布会&#xff0c;正式推出两款全新一代的智慧人行领域旗舰级产品——人脸识别门禁Y20、速通摆闸3910A。 作为国内最早进入出入口控制管理行业的企业之一&#xff0c;捷顺…

深度学习-生成式检索-论文速读-2024-09-14

深度学习-生成式检索-论文速读-2024-09-14 前言: 生成式检索&#xff08;Generative Retrieval&#xff0c; GR&#xff09;是一种结合了生成模型和检索系统的人工智能技术方法。这种方法在处理信息检索任务时&#xff0c;不仅依赖于已有数据的检索&#xff0c;还能生成新的、…

unity的学习

因为需要构建一个三维物理环境,所以学习了unity,半天就可以,非常简单清晰 1.安装 去官网下载unity hub . 然后需要下载editor,但注意已经有了vs2022就不要再下一次了,下的时候会全放c盘,再安装.c盘都装不下了. 如果美游vs2022,就先自己把vs2022安装好,再安装unity hub.(其实不…

Vue自定义指令以及项目中封装过的自定义指令

自定义指令 Vue 自定义指令是 Vue.js 框架中一个非常强大的功能&#xff0c;它允许你注册一些全局或局部的自定义 DOM 操作指令&#xff0c;以便在模板中复用。自定义指令通过 Vue.directive() 方法进行全局注册&#xff0c;或者在组件的 directives 选项中局部注册。 自定义…

YOLOV8输出预测框的坐标信息

结果&#xff1a;&#xff08;前提是对应类别的yolov8模型已经训练好&#xff09; 具体实现&#xff1a; 在ultralytics\utils\plotting.py里面 CtrlF搜索box_label 再次照片的最后一行输入&#xff1a; # 左上角cv2.putText(self.im, f"({p1[0]}, {p1[1]})", (p1…

计算机毕业设计选题推荐-共享图书管理系统-小程序/App

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

【北京迅为】《STM32MP157开发板使用手册》- 第三十一章Cortex-M4窗口看门狗实验

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

国外SIM卡有信号无法连接,如何解决?

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

[Java]SpringBoot能力进阶

配置优先级 SpringBoot中支持三种格式的配置文件 优先级: application.properties文件 > application.yml文件 > application.yaml文件 SpringBoot除了通过配置文件配置属性, 还支持Java系统属性和命令行参数的方式 进行属性配置 1.在IDEA中配置java系统属性和命令行参…

19、Python如何读写excel文件

在数据处理和分析时&#xff0c;经常使用Excel&#xff0c;而手动操作Excel可能非常繁琐和耗时。Python提供了许多强大的库和工具&#xff0c;可以方便地操作Excel文件。 在Python标准库中是不支持Excel读写的&#xff0c;我们要安装第三方库来实现。 在Python中操作Excel有多…

设计一个高质量的API接口:提升应用性能的关键步骤

在当今的软件开发世界中&#xff0c;API&#xff08;应用程序编程接口&#xff09;接口扮演着至关重要的角色。一个设计精良的API不仅能够提高开发效率&#xff0c;还能提升用户体验&#xff0c;并确保系统的可扩展性和安全性。本文将探讨如何设计一个高质量的API接口&#xff…

Golang | Leetcode Golang题解之第412题Fizz Buzz

题目&#xff1a; 题解&#xff1a; func fizzBuzz(n int) (ans []string) {for i : 1; i < n; i {sb : &strings.Builder{}if i%3 0 {sb.WriteString("Fizz")}if i%5 0 {sb.WriteString("Buzz")}if sb.Len() 0 {sb.WriteString(strconv.Itoa(i…

Davinci 大数据可视化分析

Davinci 大数据可视化分析 一、Davinci 架构设计1.1 Davinci定义1.2 Davinci 应用场景 二、Davinci 安装部署2.1 部署规划2.2 前置环境准备2.3 Davinci部署2.3.1 物料准备2.3.2 安装配置 2.4 环境变量配置2.5 初始化数据库2.5.1 创建数据库及用户 2.5.2 建表2.6 初始化配置 三、…

开源免费的NAS系统-TrueNAS CORE搭建和使用(保姆级教程)

TrueNAS CORE说明 TrueNASCORE(以前称为 FreeNAS)是世界上最受欢迎的存储操作系统,因为它使您能够构建自己的专业级存储系统,用于各种数据密集型应用程序,而无需任何软件成本。只需将其安装到硬件或虚拟机上,即可体验开源存储的真正存储自由。 TrueNAS提供了CORE和Ente…

如何用python构建简单神经网络?

今天&#xff0c;我们将运用Python来搭建一个简单的神经网络模型&#xff01;并深入浅出地探索其背后的运作原理。 多输入 提及神经网络时&#xff0c;我们可以将其视为一个高度灵活的函数来理解和应用。 为了做出准确的预测&#xff0c;我们需要构建能够同时组合多个输入的…

吸浮毛宠物空气净化器推荐,希喂、小米、有哈宠物空气净化器测评

养猫需谨慎&#xff0c;不然就要做猫奴一辈子啦&#xff01;上次堂妹来我家住几天&#xff0c;刚开始还担心和猫处不来&#xff0c;不敢去摸它&#xff0c;走的时候已经约好下次来看它的时间&#xff0c;笑死我了。毕竟猫咪这么可爱&#xff0c;很少有人可以抵抗它的魅力。 这不…

Zabbix 2024 中国峰会在上海举办,Databuff 携最业界领先研发成果重磅亮相

9月13日&#xff0c;Zabbix中国峰会在上海圆满结束。会上共进行了18场技术演讲&#xff0c;共有超过500人参加了本次盛会。 大会开始&#xff0c;Zabbix创始人Alexei Vladishev介绍了Zabbix7.0新功能以及未来的发展蓝图。 随后&#xff0c;乘云数字CEO向成钢分享了《如何打造开…

JVM 调优篇7 调优案例4- 线程溢出

一 线程溢出 1.1 报错信息 每个 Java 线程都需要占用一定的内存空间&#xff0c;当 JVM 向底层操作系统请求创建一个新的 native 线程时&#xff0c;如果没有足够的资源分配就会报此类错误。报错信息&#xff1a;java.lang.outofmemoryError:unable to create new Native Thr…