当前位置: 首页 > article >正文

剑指 Offer II 111. 计算除法


comments: true
edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20111.%20%E8%AE%A1%E7%AE%97%E9%99%A4%E6%B3%95/README.md

剑指 Offer II 111. 计算除法

题目描述

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

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

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

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

 

示例 1:

输入:equations = [["a","b"],["b","c"]], values = [2.0,3.0], queries = [["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]]
输出:[6.00000,0.50000,-1.00000,1.00000,-1.00000]
解释:
条件:a / b = 2.0, b / c = 3.0
问题:a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
结果:[6.0, 0.5, -1.0, 1.0, -1.0 ]

示例 2:

输入:equations = [["a","b"],["b","c"],["bc","cd"]], values = [1.5,2.5,5.0], queries = [["a","c"],["c","b"],["bc","cd"],["cd","bc"]]
输出:[3.75000,0.40000,5.00000,0.20000]

示例 3:

输入:equations = [["a","b"]], values = [0.5], queries = [["a","b"],["b","a"],["a","c"],["x","y"]]
输出:[0.50000,2.00000,-1.00000,-1.00000]

 

提示:

  • 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 由小写英文字母与数字组成

 

注意:本题与主站 399 题相同: https://leetcode.cn/problems/evaluate-division/

解法

方法一

Python3

深度优先搜索
图可以用来表示物体与物体之间的关系,节点代变物体,而边代变两物体之间的关系。在本问题中可以把变量看作是节点,若存在两变量之间的除法,那么这两变量对应的节点之间有一条边相连。**一个除法等式中存在被除数、除数以及商,被除数和除数用节点表示,用边的权值表示两者之间的商。**因为被除数与除数位置不同,最后的商的结果也不同,所以这个图是有向有权图。如 equations = [[“a”,“b”],[“b”,“c”]], values = [2.0,3.0] 可以用下图表示
在这里插入图片描述

由数学知识可得 a / b = a / x * x / b,这种关系在图中的表示就是,节点 a 到节点 b 之间是存在通路的,并且 a / b 等于通路各边的权重之积。因此本题本质上来说还是一个图的搜索问题,由于需要记录一条通路,所以使用深度优先搜索算法比较合适。完整代码如下,如果图中节点数量为 v,边的数量为 e,那么计算每个 queries[i] 的时间复杂度为 O(v + e)。

from collections import defaultdictclass Solution:def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:# 建双向有权图graph=defaultdict(list)st=set()for (a,b),val in zip(equations,values):graph[a].append((b,val))graph[b].append((a,1/val))st.add(a)st.add(b)#搜索路径,并计算权值累乘def dfs(st,ed):nonlocal pathif st==ed:return path #这里要return path,否则会会回溯成原始1for nx,val in graph[st]:if nx in used:continuepath*=valused.add(nx)c=dfs(nx,ed)if c!=-1: #【注意】如果存在某个无法确定的答案,则用 -1.0 替代这个答案return c  path/=valused.remove(nx)return -1  #【注意】如果存在某个无法确定的答案(也就是前面一直if st!=ed,没return path),则用 -1.0 替代这个答案res=[]for (a,b) in queries:if a not in st or b not in st:res.append(-1)continuepath=1used = {a}res.append(dfs(a, b))return res
Java
class Solution {private int[] p;private double[] w;public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {int n = equations.size();p = new int[n << 1];w = new double[n << 1];for (int i = 0; i < p.length; ++i) {p[i] = i;w[i] = 1.0;}Map<String, Integer> mp = new HashMap<>(n << 1);int idx = 0;for (int i = 0; i < n; ++i) {List<String> e = equations.get(i);String a = e.get(0), b = e.get(1);if (!mp.containsKey(a)) {mp.put(a, idx++);}if (!mp.containsKey(b)) {mp.put(b, idx++);}int pa = find(mp.get(a)), pb = find(mp.get(b));if (pa == pb) {continue;}p[pa] = pb;w[pa] = w[mp.get(b)] * values[i] / w[mp.get(a)];}int m = queries.size();double[] res = new double[m];for (int i = 0; i < m; ++i) {String c = queries.get(i).get(0), d = queries.get(i).get(1);Integer id1 = mp.get(c), id2 = mp.get(d);if (id1 == null || id2 == null) {res[i] = -1.0;} else {int pa = find(id1), pb = find(id2);res[i] = pa == pb ? w[id1] / w[id2] : -1.0;}}return res;}private int find(int x) {if (p[x] != x) {int origin = p[x];p[x] = find(p[x]);w[x] *= w[origin];}return p[x];}
}
C++
class Solution {
public:vector<int> p;vector<double> w;vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {int n = equations.size();for (int i = 0; i < (n << 1); ++i) {p.push_back(i);w.push_back(1.0);}unordered_map<string, int> mp;int idx = 0;for (int i = 0; i < n; ++i) {auto e = equations[i];string a = e[0], b = e[1];if (mp.find(a) == mp.end()) mp[a] = idx++;if (mp.find(b) == mp.end()) mp[b] = idx++;int pa = find(mp[a]), pb = find(mp[b]);if (pa == pb) continue;p[pa] = pb;w[pa] = w[mp[b]] * values[i] / w[mp[a]];}int m = queries.size();vector<double> res;for (int i = 0; i < m; ++i) {string c = queries[i][0], d = queries[i][1];if (mp.find(c) == mp.end() || mp.find(d) == mp.end())res.push_back(-1.0);else {int pa = find(mp[c]), pb = find(mp[d]);res.push_back(pa == pb ? w[mp[c]] / w[mp[d]] : -1.0);}}return res;}int find(int x) {if (p[x] != x) {int origin = p[x];p[x] = find(p[x]);w[x] *= w[origin];}return p[x];}
};
Go
var p []int
var w []float64func calcEquation(equations [][]string, values []float64, queries [][]string) []float64 {n := len(equations)p = make([]int, (n<<1)+10)w = make([]float64, (n<<1)+10)for i := 0; i < (n<<1)+10; i++ {p[i] = iw[i] = 1.0}mp := make(map[string]int)idx := 1for i, e := range equations {a, b := e[0], e[1]if mp[a] == 0 {mp[a] = idxidx++}if mp[b] == 0 {mp[b] = idxidx++}pa, pb := find(mp[a]), find(mp[b])if pa == pb {continue}p[pa] = pbw[pa] = w[mp[b]] * values[i] / w[mp[a]]}var res []float64for _, q := range queries {c, d := q[0], q[1]if mp[c] == 0 || mp[d] == 0 {res = append(res, -1.0)} else {pa, pb := find(mp[c]), find(mp[d])if pa == pb {res = append(res, w[mp[c]]/w[mp[d]])} else {res = append(res, -1.0)}}}return res
}func find(x int) int {if p[x] != x {origin := p[x]p[x] = find(p[x])w[x] *= w[origin]}return p[x]
}
Swift
class Solution {private var parent = [Int]()private var weight = [Double]()func calcEquation(_ equations: [[String]],_ values: [Double],_ queries: [[String]]) -> [Double] {let n = equations.countparent = Array(0..<(n * 2))weight = Array(repeating: 1.0, count: n * 2)var map = [String: Int]()var index = 0for i in 0..<n {let a = equations[i][0]let b = equations[i][1]if map[a] == nil {map[a] = indexindex += 1}if map[b] == nil {map[b] = indexindex += 1}let pa = find(map[a]!)let pb = find(map[b]!)if pa != pb {parent[pa] = pbweight[pa] = weight[map[b]!] * values[i] / weight[map[a]!]}}var result = [Double]()for query in queries {let (c, d) = (query[0], query[1])if let id1 = map[c], let id2 = map[d], find(id1) == find(id2) {result.append(weight[id1] / weight[id2])} else {result.append(-1.0)}}return result}private func find(_ x: Int) -> Int {if parent[x] != x {let origin = parent[x]parent[x] = find(parent[x])weight[x] *= weight[origin]}return parent[x]}
}

相关文章:

剑指 Offer II 111. 计算除法

comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20111.%20%E8%AE%A1%E7%AE%97%E9%99%A4%E6%B3%95/README.md 剑指 Offer II 111. 计算除法 题目描述 给定一个变量对数组 equations 和一个实数值数组 values 作…...

掌握 WRF/Chem 模式:突破大气环境研究技术瓶颈的关键

技术点目录 第一部分、WRF-Chem模式应用案例和理论基础第二部分、Linux环境配置及WRF-CHEM第三部分、WRF-Chem模式编译&#xff0c;排放源制作第四部分、WRF-Chem数据准备&#xff08;气象、排放、初边界条件等&#xff09;&#xff0c;案例实践第五部分、模拟结果提取、数据可…...

linux性能监控的分布式集群 prometheus + grafana 监控体系搭建

prometheusgrafana分布式集群资源监控体系搭建 前言一、安装 prometheus二、在要监控的服务器上安装监听器三、prometheus服务器配置四、grafana配置大屏五、创建Linux监控看板五、监控windows服务器注意事项 前言 Prometheus 是一个开源的 ​分布式监控系统 和 ​时间序列数据…...

数字化转型 2.0:AI、低代码与智能分析如何重塑企业竞争力?

引言&#xff1a;数字化转型进入2.0时代 在过去的十几年里&#xff0c;企业的数字化转型&#xff08;1.0&#xff09;主要围绕信息化和自动化展开&#xff0c;例如引入ERP、CRM等系统&#xff0c;提高办公效率&#xff0c;减少人为失误。然而&#xff0c;随着市场竞争加剧&…...

柔性PZT压电薄膜触觉传感器在人形机器人的应用

柔性PZT压电薄膜声阻抗与人体组织匹配好&#xff0c;具有可弯曲性&#xff0c;可以贴附在非平整物体表面进行使用&#xff1b;而且具有受力后易弯曲的特点&#xff0c;器件的输出信号强&#xff0c;可用于穿戴产品&#xff0c;比如可以制作多路脉搏传感器用于智能多通道脉诊仪&…...

基于SpringBoot的“校园招聘网站”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“校园招聘网站”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统整体功能图 局部E-R图 系统首页界面 系统注册…...

基于FPGA的DDS连续FFT 仿真验证

基于FPGA的 DDS连续FFT 仿真验证 1 摘要 本文聚焦 AMD LogiCORE IP Fast Fourier Transform (FFT) 核心,深入剖析其在 FPGA 设计中的应用。该 FFT 核心基于 Cooley - Tukey 算法,具备丰富特性,如支持多种数据精度、算术类型及灵活的运行时配置。文中详细介绍了其架构选项、…...

由LAC自动建立L2TP实验

一、实验拓扑: 二、实验配置 1.LAC的配置 基础配置: [LAC]int g 0/0/0 [LAC-GigabitEthernet1/0/0]ip address 192.168.0.1 24 [LAC]int g 1/0/0 [LAC-GigabitEthernet1/0/0]ip address 10.1.1.254 24 [LAC-GigabitEthernet1/0/0]int g1/0/1 [LAC-GigabitEthernet1/0/1]ip ad…...

内网渗透(CSMSF) 构建内网代理的全面指南:Cobalt Strike 与 Metasploit Framework 深度解析

目录 1. Cobalt Strike 在什么情况下会构建内网代理&#xff1f; 2. Cobalt Strike 构建内网代理的主要作用和目的是什么&#xff1f; 3. Cobalt Strike 如何构建内网代理&#xff1f;需要什么条件和参数&#xff1f; 条件 步骤 参数 4. Cobalt Strike 内网代理能获取什…...

[AI速读]混合语言IP集成:挑战与高效解决方案

在现代SoC(系统级芯片)设计中,IP(知识产权模块)复用是提升开发效率的关键。然而,当设计涉及多种硬件描述语言(如SystemVerilog、VHDL、SystemC)时,如何高效集成不同语言的IP模块成为一大难题。本文将从实际设计场景出发,探讨混合语言IP集成的核心挑战,并介绍一套方法…...

利用ffmpeg库实现音频Opus编解码

一、编译与环境配置 ‌libopus库集成‌ 需在编译FFmpeg时添加--enable-libopus参数&#xff0c;编译前需先安装libopus源码并配置动态库路径‌。最新FFmpeg 7.1版本默认支持Opus的浮点运算优化和VBR/CVBR模式‌。 ‌多平台兼容性‌ Opus支持Windows/Linux/macOS平台&#xff0…...

SAP FAGLL03 追加并显示描述字段

目录 1、新建一个结构2、操作FAGLPOSX结构3、新建一个BADI 1、新建一个结构 1.1、先在SE11中新建一个结构&#xff1a;ZZADD_FIELDS_FAGL&#xff0c;把我们要显示的描述字段放在这个结构中 2、操作FAGLPOSX结构 2.1、在FAGLPOSX结构中选择Append Structure&#xff0c;把我…...

Linux Vim 寄存器 | 从基础分类到高级应用

注&#xff1a;本文为 “vim 寄存器” 相关文章合辑。 英文引文&#xff0c;机翻未校。 中文引文&#xff0c;略作重排。 未整理去重&#xff0c;如有内容异常&#xff0c;请看原文。 Registers 寄存器 Learning Vim registers is like learning algebra for the first ti…...

Ubuntu版免翻墙搭建BatteryHistorian

摘要 昨天安装了一个翻墙版本的很不好用&#xff0c;主要是网络不稳定&#xff0c;故于是换了一个免翻墙的docker镜像。但是发现还是很难用。又安装了一个window版本的免翻墙的BatteryHistorian。明天再分享下Windows的免翻墙的BatteryHistorian步骤。 安装好Docker了就直接d…...

Django Rest Framework 创建纯净版Django项目部署DRF

描述创建纯净版的Django项目和 Django Rest Framework 环境的部署 一、创建Django项目 1. 环境说明 操作系统 Windows11python版本 3.9.13Django版本 V4.2.202. 操作步骤(在Pycharm中操作) 创建Python项目drfStudy、虚拟环境 ​虚拟环境中安装 jdangopip install django==4.…...

深度洞察:DeepSeek 驱动金融行业智能化转型变革

该文章为软件测评&#xff0c;不是广告&#xff01;&#xff01;&#xff01;&#xff01; 目录 一.金融行业的智能化转型浪潮​ 二.DeepSeek的核心技术剖析 1.DeepSeek 模型的金融智慧​ 2.实时联网搜索&#xff1a;把握金融市场脉搏​ 3.RAG 能力&#xff1a;铸就精准金…...

面试题精选《剑指Offer》:JVM类加载机制与Spring设计哲学深度剖析-大厂必考

一、JVM类加载核心机制 &#x1f525; 问题5&#xff1a;类从编译到执行的全链路过程 完整生命周期流程图 关键技术拆解 编译阶段 查看字节码指令&#xff1a;javap -v Robot.class 常量池结构解析&#xff08;CONSTANT_Class_info等&#xff09; 类加载阶段 // 手动加载…...

【CXX-Qt】2.1.1 为 WebAssembly 构建

CXX-Qt 及其编写的应用程序可以编译为 WebAssembly&#xff0c;但存在一些限制。以下是关于如何为 WASM 目标构建的详细说明。 你需要安装 Qt for WebAssembly。下一篇将展示已测试的版本。 此外&#xff0c;如果尚未完成&#xff0c;请从此处克隆 emsdk git 仓库。 使用正确…...

AUTOSAR Communication Services - COM:(二)COM的常见API用法整理

备注&#xff1a;COM-API常用用法整理&#xff0c;持续更新 一、用户I-PDU发送回调中&#xff0c;指定发送对应DBC的信号值 boolean Rte_COMIPduCallout_signal(PduIdType id, PduInfoType *ptr) {static uint8 ucCheckSum 0;// Calculate checksumif (ucCheckSum > 15)u…...

掌握些许 IPv6 要点,windows 远程桌面安全便利两相宜!

掌握这些要点&#xff0c;Windows 远程桌面安全便利两相宜&#xff01; 在日常办公中&#xff0c;许多人会用到 Windows 系统的远程桌面功能。但在实际使用时&#xff0c;会遇到内网计算机难以通过运营商的动态 ip 与多层 NAT 向互联网暴露端口的技术问题&#xff0c;和计算机…...

Spring Boot整合Apache BookKeeper教程

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Spring Boot整合Apache BookKeeper教程 1. 简介 Apache BookKeeper 是一个高性能、持久化的分布式日志存储系统&#xff0c;适用于需要强一致性和高吞吐量的…...

【Linux进程】——进程的程序地址空间

目录 前言 1.程序地址空间 1.1区域划分 1.2程序地址空间的本质 1.3程序地址空间分配原则 2.数据寻找 2.1补充&#xff1a;进程挂起 结语 前言 在Linux系统的神秘世界里&#xff0c;进程就像是一个个小工匠&#xff0c;各自忙碌地完成着不同的任务。你是否想过&#xff…...

边缘云原生操作系统的设计与思考

资料来源&#xff1a;火山引擎-开发者社区 边缘云行业现状和发展历程 从 06 年 AWS 推出 EC2 、S3 到今天已经过去了 18 年&#xff0c;云计算早已不是一个新鲜词汇&#xff0c;从当前业务来看&#xff0c;我们能看到云计算从中心到中心边缘的发展趋势&#xff0c;为什么会有 这…...

Jenkins muti-configuration-project 中调用pipeline project

Jenkins muti-configuration-project 中调用pipeline project 解决方案示例练习1. 多配置项目设置&#xff1a;2. 触发器配置&#xff1a;3. Pipeline 项目 Jenkinsfile&#xff1a; 解决方案 创建多配置项目&#xff1a; 在 Jenkins 中创建一个新的多配置项目。在“配置矩阵…...

Gdiplus(也就是GDI+)使用

篇一&#xff1a; Gdiplus(也就是GDI)使用步骤&#xff1a; 1.包括相应的头文件及引入相应的lib #include <GdiPlus.h> #pragma comment(lib, "gdiplus.lib") using namespace Gdiplus;//如果没有using namespace Gdiplus;就需要添加“命名空间作用域符” …...

AI学习——卷积神经网络(CNN)入门

作为人类&#xff0c;我们天生擅长“看”东西&#xff1a;一眼就能认出猫狗、分辨红绿灯、读懂朋友的表情……但计算机的“眼睛”最初是一片空白。直到卷积神经网络&#xff08;CNN&#xff09;​的出现&#xff0c;计算机才真正开始理解图像。今天&#xff0c;我们就用最通俗的…...

双指针算法-day14(分组循环)

1.最长奇偶子数组 题目 解析 分组循环模板&#xff1a; 简单来说&#xff1a; 第一步&#xff1a;指针遍历找到满足条件的开头下标&#xff0c;并用 start i 记录开头&#xff1b;第二步&#xff1a;指针不断右移寻找满足条件的最长子数组&#xff1b;第三步&#xff1a;更新…...

Linux基础开发工具--gdb的使用

目录 安装准备&#xff1a; 1. 背景 2. 开始使用 3. 做一个Linux第一个小程序&#xff0d;进度条 安装准备&#xff1a; 对于gdb的学习使用&#xff0c;为了方便大家学习&#xff0c;我建议大家先安装一个cgdb进行学习&#xff0c;这样方便观察操作与学习gdb。 用以下…...

垃圾回收算法(Garbage Collection)深度解析

垃圾回收算法&#xff08;Garbage Collection&#xff09;深度解析 核心思想 垃圾回收核心目标&#xff1a; 定位存活对象 、回收死亡对象可达性分析算法、空间复用优化 生死判定原理 可达性分析法&#xff08;Reachability Analysis&#xff09; 通过GC Roots&#xff08…...

基于Matlab实现语音识别算法(源码+数据)

语音识别技术是现代信息技术中的一个重要领域&#xff0c;特别是在人机交互、智能设备、智能家居、自动驾驶等多个领域有着广泛应用。MATLAB作为一种强大的数值计算和数据可视化环境&#xff0c;因其易用性和丰富的库支持&#xff0c;常被用来实现复杂的算法&#xff0c;包括语…...