Leetcode 399. 除法求值
- Leetcode 399. 除法求值
- 题目
- 给你一个变量对数组 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 的情况,且不存在任何矛盾的结果。
- 1 <= equations.length <= 20
- equations[i].length == 2
- 1 <= Ai.length, Bi.length <= 5
- values.length == equations.length
- 0.0 < values[i] <= 20.0
- 1 <= queries.length <= 20
- queries[i].length == 2
- 1 <= Cj.length, Dj.length <= 5
- Ai, Bi, Cj, Dj 由小写英文字母与数字组成
- 解法
- 并查集:将 equations 与 values 的值放入并查集中:parent(equations[i][0])=equations[i][1] 代表 equations[i][0]/equations[i][1],同时设置:parentValue(equations[i][0])=values[i]、parentValue(equations[i][1])=1
- 并查集必须路径压缩:parent(son)=father 与 parent(father)=grandfather 压缩为:parent(son)=grandfather,新parentValue(son)=旧parentValue(son) * parentValue(father)(=son/father * father/grandfather)
- 合并两个并查集:son1、son2 需要先路径压缩:ancestor1 = parent(son1),ancestor2 = parent(son2),再合并两个元素的祖先:parent(ancestor1)=ancestor2,然后计算值:parentValue(ancestor1)=value / parentValue(son1) * parentValue(son2) (=son1/son2 / son1/ancestor1 * son2/ancestor2)
- 循环 queries 分类讨论搜索答案,其实是求出:queries[0]/queries[1],分类讨论:
- 如果 queries[0] 或 queries[1] 任一元素不再任何并查集中,则返回 -1.0(equations 没有出现过)
- 如果 queries[0] 或 queries[1] 不再同一个并查集中,则返回 -1.0(相同并查集中元素代表可以通过计算获得比例,不同并查集代表无法产生交集)
- 否则 计算 parentValue(queries[0])/parentValue(queries[1]) 就是答案((queries[0]/queries[根])/(queries[1]/queries[根]))
- equations.length(== values.length)为 n、queries.length 为 m,equations 里不同字符的个数为 x,时间复杂度:O((n+m)*α(x)),空间复杂度:O(x)
- 代码
/*** 并查集:将 equations 与 values 的值放入并查集中:parent(equations[i][0])=equations[i][1] 代表 equations[i][0]/equations[i][1],* 同时设置:parentValue(equations[i][0])=values[i]、parentValue(equations[i][1])=1* 并查集必须路径压缩:parent(son)=father 与 parent(father)=grandfather 压缩为:parent(son)=grandfather* 新parentValue(son)=旧parentValue(son) * parentValue(father)(=son/father * father/grandfather)* 合并两个并查集:son1、son2 需要先路径压缩:ancestor1 = parent(son1),ancestor2 = parent(son2),* 再合并两个元素的祖先:parent(ancestor1)=ancestor2,然后计算值:parentValue(ancestor1)=value / parentValue(son1) * parentValue(son2)* (=son1/son2 / son1/ancestor1 * son2/ancestor2)* 循环 queries 分类讨论搜索答案,其实是求出:queries[0]/queries[1],分类讨论:* 如果 queries[0] 或 queries[1] 任一元素不再任何并查集中,则返回 -1.0(equations 没有出现过)* 如果 queries[0] 或 queries[1] 不再同一个并查集中,则返回 -1.0(相同并查集中元素代表可以通过计算获得比例,不同并查集代表无法产生交集)* 否则 计算 parentValue(queries[0])/parentValue(queries[1]) 就是答案((queries[0]/queries[根])/(queries[1]/queries[根]))* equations.length(== values.length)为 n、queries.length 为 m,equations 里不同字符的个数为 x,时间复杂度:O((n+m)*α(x)),空间复杂度:O(x)*/public double[] solution(List<List<String>> equations, double[] values, List<List<String>> queries) {// 判空if (equations == null || values == null || queries == null || equations.size() != values.length) {return new double[0];}// 将 equations 与 values 的值放入并查集中int len = values.length;Map<String, String> parent = new HashMap<>((len / 3) << 2);Map<String, Double> parentValue = new HashMap<>((len / 3) << 2);for (int i = 0; i < len; i++) {// equations 新参数初始化:指向自己,值为 1.0initEquations(equations.get(i).get(0), parent, parentValue);initEquations(equations.get(i).get(1), parent, parentValue);union(equations.get(i).get(0), equations.get(i).get(1), parent, values[i], parentValue);// System.out.println(parent);// System.out.println(parentValue);}// 循环 queries 分类讨论搜索答案,其实是求出:queries[0]/queries[1],分类讨论double[] answer = new double[queries.size()];int index = 0;for (List<String> queriesSingle : queries) {answer[index] = getAnswerByUnionFind(parent, queriesSingle.get(0), queriesSingle.get(1), parentValue);index++;}return answer;}private void initEquations(String factor, Map<String,String> parent, Map<String,Double> parentValue) {if (!parent.containsKey(factor)) {parent.put(factor, factor);parentValue.put(factor, 1.0);}}private void union(String son, String father, Map<String,String> parent, double value, Map<String, Double> parentValue) {String sonAncestor = find(son, parent, parentValue);String fatherAncestor = find(father, parent, parentValue);parent.put(sonAncestor, fatherAncestor);parentValue.put(sonAncestor, value / parentValue.get(son) * parentValue.get(father));}private String find(String factor, Map<String,String> parent, Map<String, Double> parentValue) {if (!parent.containsKey(factor)) {return null;}if (factor.equals(parent.get(factor))) {return factor;}String ancestor = find(parent.get(factor), parent, parentValue);// 路径压缩parentValue.put(factor, parentValue.get(factor) * parentValue.get(parent.get(factor)));parent.put(factor, ancestor);return ancestor;}private double getAnswerByUnionFind(Map<String,String> parent, String q0, String q1, Map<String, Double> parentValue) {if (q0 == null || q1 == null) {return -1.0;} else if (find(q0, parent, parentValue) == null || find(q1, parent, parentValue) == null) {return -1.0;} else if (!find(q0, parent, parentValue).equals(find(q1, parent, parentValue))) {return -1.0;} else {return parentValue.get(q0)/parentValue.get(q1);}}
相关文章:
Leetcode 399. 除法求值
Leetcode 399. 除法求值题目 给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi values[i] 。每个Ai 或 Bi 是一个表示单个变量的字符串。另有一些以数组 queries 表示的问题&am…...
kotlin协程并发/并行与串行互相切换,CoroutineScope与await
kotlin协程并发/并行与串行互相切换,CoroutineScope与await import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.time.LocalTimefun main(args: Arra…...
初识linux之简单了解TCP协议与UDP协议
目录 一、理解源IP地址和目的IP地址 二、端口号 1. 为什么要有端口号 2. 理解端口号 3. 源端口号和目的端口号 三、初步了解TCP协议和UDP协议 1. 初步认识TCP协议 2. 初步认识UDP协议 3. 可靠传输与不可靠传输 四、网络字节序 1. 网络字节序的概念 2. 如何形成网络…...
【String——简单使用】
文章目录 String1. 字符串定义和初始化2. 字符串基本操作2.1 访问单个字符2.2 修改字符串内容2.3 字符串查找和比较 3. 常用字符串函数3.1 length() 和 size()3.2 empty()3.3 substr()3.4 c_str() 4.字符与整形之间相互转换4.1 char 类型转 int 类型4.2 int 类型转 char 类型4.…...
Python下Taobao封装API接口的优势
Python是一门面向对象编程的语言,封装是面向对象编程中的一种重要概念,它把数据和方法包装在一起,实现了对数据的保护和控制。Python封装接口的优势如下: 1.安全性 封装可以保证数据的安全性,禁止外部对数据的直接访…...
LeetCode 49 字母异位词分组
LeetCode 49 字母异位词分组 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/group-anagrams/description/ 博主Github:https://github.com/GDUT-Rp/LeetCode 题目: 给你一个字符串数组&#x…...
( 链表) 142. 环形链表 II——【Leetcode每日一题】
❓142. 环形链表 II 难度:中等 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定…...
论文解读 | 基于改进点对特征的点云6D姿态估计
原创 | 文 BFT机器人 01 摘要 点对特征(PPF)方法已被证明是一种有效的杂波和遮挡下的姿态估计方法。 文章的改进方法主要包括: (1)一种基于奇偶规则求解封闭几何的法向的方法; (2)通过将体素网格划分为等效角度单元的有效降采样方法; (3)基于拟合点的验证步骤。在真实杂波数据集…...
Shell脚本while循环语句应用
记录:433 场景:Shell脚本while循环语句应用。Shell脚本while循环语句应用。while do done、while : do done、while true do done。 版本:CentOS Linux release 7.9.2009。 1.while常用格式 1.1格式一:while do done while c…...
Kubernetes Dashboard + Ingress 及其 yaml 文件分析
概述 记录部署Dashboard Ingress的具体过程及其 yaml 文件分析 Dashboard Yaml # Copyright 2017 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the Li…...
【SpringCloud组件——Nacos】
前置准备: 分别提供订单系统(OrderService)和用户系统(UserService)。订单系统主要负责订单相关信息的处理,用户系统主要负责用户相关信息的处理。 一、服务注册与发现 1.1、在父工程当中引入Nacos依赖 …...
pinia状态管理 用法
Pinia是一个用于vue的状态管理库,类似于vuex,是vue的另一种状态管理工具。 Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态。实际上,Pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名pinia&am…...
Oracle客户端版本安装
一、版本准备 Oracle版本下载官网:Instant Client for Linux x86-64 (64-bit) | Oracle 中国 进入网站下载对应的oracle版本,通常环境所用的包有:basic、sdk、sdkplus三个包。包的类型分为rpm和zip包,均可以下载,当前…...
基于Android studio二手车交易系统app
客户端: 用户注册:通过输入用户名,密码,所在地,联系地址以及电话和电子邮件等信息进行用户信息的注册。 二手车查看:用户注册登录系统后,可以查看二手车的基本信息,通过二手车的品牌…...
【LCD应用编程】绘制点、线、矩形框
之前获取LCD屏幕参数信息时了解到,LCD屏是 FrameBuffer 设备,操作 FrameBuffer 设备 其实就是在读写 /dev/fb0 文件。除此之外,LCD屏上包含多个像素点,绘制点、线、矩形框本质是在修改这些像素点的颜色。 目录 1、定义 lcd_color…...
第八篇、基于Arduino uno,获取MAX30102心率传感器的心率信息——结果导向
0、结果 说明:先来看看串口调试助手显示的结果,第一个值是原始的IR值,第二个值是实时的心跳,第三个值是平均心跳,如果是你想要的,可以接着往下看。 1、外观 说明:MAX30102心率传感器的外观如下…...
【MySQL】MySQL主从同步延迟原因与解决方案
文章目录 一、MySQL数据库主从同步延迟产生的原因二、关于DDL和DML三、主从延时排查方法四、解决方案3.1 解决从库复制延迟的问题:3.2 MySql数据库从库同步其他问题及解决方案 一、MySQL数据库主从同步延迟产生的原因 MySQL的主从复制都是单线程的操作,…...
学C的第二十二天【深度剖析数据在内存中的存储:1. 数据类型介绍;2. 整型在内存中的存储】
相关代码gitee自取:C语言学习日记: 加油努力 (gitee.com) 接上期:学C的第二十一天【初阶测评讲解:1. 计算递归了几次;2. 判断 do while 循环执行了几次;3. 求输入的两个数的最小公倍数;4. 将一句话的单词进…...
测试计划模板一
测试计划 修订历史记录 版本 日期 AMD 修订者 说明 1.0 XXXX年XX月XX (A-添加,M-修改,D-删除) 目录 1. 简介.. 4 1. 1目的... 4 1. 2背景... 4...
【利用AI让知识体系化】5种创建型模式
文章目录 创建型模式简介工厂模式抽象工厂模式单例模式建造者模式原型模式 创建型模式 简介 创建型模式,顾名思义,是用来创建对象的模式。在软件开发中,对象的创建往往比一般的编程任务更为复杂,可能涉及到一些琐碎、复杂的过程…...
避坑指南:R语言中XGBoost回归建模的5个常见错误与SHAP分析的正确姿势
避坑指南:R语言中XGBoost回归建模的5个常见错误与SHAP分析的正确姿势 在数据科学领域,XGBoost因其出色的预测性能而广受欢迎,而SHAP(Shapley Additive Explanations)则为模型解释提供了强大的数学基础。然而࿰…...
告别随机色!YOLOv7检测框颜色固定与高级样式自定义全攻略(从PIL到OpenCV)
YOLOv7检测框样式深度定制:从颜色固化到多语言字体支持实战 在计算机视觉项目的实际部署中,检测框的可视化效果往往直接影响最终用户体验。YOLOv7作为当前主流的目标检测框架,其默认的随机颜色分配和有限的字体支持可能无法满足专业场景需求。…...
深度解析:利用pmap+gdb精准诊断Linux进程内存异常
1. 为什么需要pmapgdb组合排查内存问题 第一次遇到线上服务内存爆涨时,我盯着top命令里那个不断攀升的RES数值束手无策。传统的内存监控工具就像医院的体温计,只能告诉你"发烧了",但查不出具体病因。这就是pmap和gdb这对"黄金…...
2025最权威的十大AI辅助写作助手推荐
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 当今之时,人工智能技术已然深度介入至毕业论文的写作进程里面,于文献…...
告别B站缓存格式困扰:m4s-converter让视频文件处理效率提升80%
告别B站缓存格式困扰:m4s-converter让视频文件处理效率提升80% 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 一、痛点直击…...
快速生成git安装配置脚本,快马平台助你一键搭建版本控制环境
最近在帮团队新成员配置开发环境时,发现git安装这个看似简单的步骤,其实藏着不少坑。不同操作系统下的安装方式差异很大,新手经常要反复查阅各种教程。于是我用InsCode(快马)平台快速搭建了一个git安装配置助手,整个过程比想象中顺…...
普通程序员有必要深入学习JVM底层原理吗?
对于JVM,我想大部分小伙伴都是要面试了才会去学,其余时间基本不会去看。但值得一说的是,当你工作多年之后,你遇到的项目会越来越复杂,遇到的问题也会越来越复杂:各种古怪的内存溢出,死锁&#x…...
大模型开发避坑:彻底理清 Skill(技能)与 MCP(模型 上下文协议)的本质区别与协同
在目前的 AI 应用开发圈子里,各种新名词层出不穷:Skill(技能)、Plugin(插件)、Function Calling(函数调用)、Tool(工具)、MCP(模型上下文协议&…...
万象视界灵坛部署案例:边缘设备(Jetson Orin)轻量化CLIP推理部署
万象视界灵坛部署案例:边缘设备(Jetson Orin)轻量化CLIP推理部署 1. 项目概述 万象视界灵坛(Omni-Vision Sanctuary)是一款基于OpenAI CLIP模型的高级多模态智能感知平台。该平台通过创新的像素风格界面设计…...
iOS高级开发工程师技术体系与民航行业实践深度解析
第一章 iOS开发技术核心体系 1.1 Swift与Objective-C双语言生态 现代iOS开发需要掌握两种核心语言的技术特点: // Swift类型安全示例 enum FlightStatus {case scheduled, departed, landed, canceled }var currentStatus: FlightStatus = .scheduled// 编译器会阻止非法状…...
