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

解题思路

  1. 这道题用到并查集,先定义一个并查集对象方便操作里面的变量
  2. 子结点权值是指子结点到父结点(注意不是到根),即 子结点是被除数,父结点是除数
  3. 把每个点的权值至1,父结点为其本身
  4. 查到两个点的根是否在同一个集合
    1. 不在   则把两个根拼接,拼接方法是除数的根作为被除数根的根,拼接后被除数的根就变成集合中的子结点,这时要计算该子结点的权值
    2. 就要根据 两个结点到它们的根的权值之积与 两个结点之间的value值 计算出 两结点其中被除数的根的权值,并且为其赋值
  5. 在同一个集合则不用拼接
  6. 优化方案是边查询,边压缩路径,边修改权值(压缩路径后必须修改权值,不然会导致路径和权值不匹配)
  7. 注意两个不同集合的数是不能计算出结果的,返回-1.0,因为分数约不了
  8. 最后计算集合中任意两个结点的值时,要先计算一个数到根的权值,再计算第二个数到根的权值,把两个权值相除,由于同一个集合根一样,可以约掉一个,所以最终可以计算出两数之商
public class Solution {public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {int equationsSize = equations.size();UnionFind unionFind = new UnionFind(2 * equationsSize);// 第 1 步:预处理,将变量的值与 id 进行映射,使得并查集的底层使用数组实现,方便编码Map<String, Integer> hashMap = new HashMap<>(2 * equationsSize);int id = 0;for (int i = 0; i < equationsSize; i++) {List<String> equation = equations.get(i);String var1 = equation.get(0);String var2 = equation.get(1);if (!hashMap.containsKey(var1)) {hashMap.put(var1, id);id++;}if (!hashMap.containsKey(var2)) {hashMap.put(var2, id);id++;}unionFind.union(hashMap.get(var1), hashMap.get(var2), values[i]);}// 第 2 步:做查询int queriesSize = queries.size();double[] res = new double[queriesSize];for (int i = 0; i < queriesSize; i++) {String var1 = queries.get(i).get(0);String var2 = queries.get(i).get(1);Integer id1 = hashMap.get(var1);Integer id2 = hashMap.get(var2);if (id1 == null || id2 == null) {res[i] = -1.0d;} else {res[i] = unionFind.isConnected(id1, id2);}}return res;}private class UnionFind {private int[] parent;/*** 指向的父结点的权值*/private double[] weight;public UnionFind(int n) {this.parent = new int[n];this.weight = new double[n];for (int i = 0; i < n; i++) {parent[i] = i;weight[i] = 1.0d;}}public void union(int x, int y, double value) {int rootX = find(x);int rootY = find(y);if (rootX == rootY) {return;}parent[rootX] = rootY;// 关系式的推导请见「参考代码」下方的示意图weight[rootX] = calRootWeight(y) * value / calRootWeight(x);}public double calRootWeight(int x){double w=1;while(x!=parent[x]){w*=weight[x];x=parent[x];}return w;}/*** 路径压缩** @param x* @return 根结点的 id*/public int find(int x) {int t=0;if (x != parent[x]) {t= find(parent[x]);}else {return x;}return t;}public double calsumVal(int x){double w=1.0d;while(x!=parent[x]){w*=weight[x];x=parent[x];}return w;}public double isConnected(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX == rootY) {return calsumVal(x)/calsumVal(y);} else {return -1.0d;}}}
}

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

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

相关文章

linux的搭建以及网关配置

Linux 目前国内 Linux 更多的是应用于服务器上,而桌面操作系统更多使用的是 Windows 安装linux虚拟机 网址 VMware下载网址 点击Workstation 16 Pro for Windows下载 安装CentOS centO下载网址 依次点击 7.6.1810/ isos/ x86_64/ CentOS-7-x86_64-DVD-1810.…

编写一个最简单的Windows服务端和客户端程序

2023年8月4日&#xff0c;周五上午 编译器 我使用vs2022作为编译器 纯享版 服务端负责发送Hello给客户端&#xff0c; 客户端负责把Hello接收并打印出来。 服务端代码 #include<winsock2.h> #include<string.h> #pragma comment(lib, "ws2_32.lib")i…

Vue3 watch监听器

概览&#xff1a;watch监听器的定义以及使用场景。在vue3中的监听器的使用方式&#xff0c;watch的三个参数&#xff0c;以及进一步了解第一个参数可以是一个属性&#xff0c;也可以是一个数组的形式包含多个属性。 watch在vue3和vue2中的使用&#xff1a; vue3中&#xff1a…

使用Jackson自定义序列化操作(Jackson – Custom Serializer)

目录 Standard Serialization of an Object GraphCustom Serializer on the ObjectMapperCustom Serializer on the Class Standard Serialization of an Object Graph Data NoArgsConstructor AllArgsConstructor public class Item {public int id;public String itemName;p…

java中pageHelper插件各个函数介绍

PageHelper是一个用于对MyBatis进行分页查询的Java插件。它提供了一组函数来配置和使用分页功能。以下是PageHelper插件中几个常用函数的介绍&#xff1a; startPage(int pageNum, int pageSize) 该函数用于开启分页查询&#xff0c;指定要查询的页码&#xff08;pageNum&#…

uniapp-疫情应急管理系统学生端

1 疫情资讯展示 <template><view class"container"><uni-section title"自定义卡片内容" type"line"><uni-card title"基础卡片" class"card-box" v-for"(item,index) in epidemicNewsList"…

优雅地切换node版本(windows)

文章目录 1、下载并安装nvm2、nvm的使用3、处理npm版本与nodejs版本不匹配问题&#xff08;通常不会有这个问题&#xff09; 1、下载并安装nvm 卸载已安装的node&#xff1a;控制面板-程序-找到node并卸载 通常在控制面板中卸载后&#xff0c;nodejs目录、环境变量、注册表就自…

oracle会话打满

1.查看当前连接情况 col machine for a20 col program for a40 col sql_id for a20 set linesize 300 set pagesize 300 select machine,program,sql_id,count(1) from v$session group by machine,program,sql_id order by 4 desc;MACHINE PROGRAM SQL_ID …

面试之快速学习c++11 - C++返回值类型后置(跟踪返回值类型) 和 using

学习地址&#xff1a; http://c.biancheng.net/view/3730.html 1. C返回值类型后置&#xff08;跟踪返回值类型&#xff09; eg: template <typename R, typename T, typename U> R add1(T t, U u) {return tu; }void testAdd1() {int a 1;float b 1.0;auto result …

【MySQL】DQL语句

8&#xff0c;DQL 下面是黑马程序员展示试题库数据的页面 页面上展示的数据肯定是在数据库中的试题库表中进行存储&#xff0c;而我们需要将数据库中的数据查询出来并展示在页面给用户看。上图中的是最基本的查询效果&#xff0c;那么数据库其实是很多的&#xff0c;不可能在将…

Codeforces Round 881 (Div. 3)F1题解

文章目录 [Omsk Metro (simple version)](https://codeforces.com/contest/1843/problem/F1)问题分析1.分析如何知道根节点到某个结点的区间内是否存在一个子段和为k2.方法1使用树形DP来动态维护每个节点到根节点的最大子段和和最小子段和代码 Omsk Metro (simple version) 问题…

STM32使用HAL库中外设初始化MSP回调机制及中断回调机制详解

STM32使用HAL库之Msp回调函数 1.问题提出 在STM32的HAL库使用中&#xff0c;会发现库函数大都被设计成了一对&#xff1a; HAL_PPP/PPPP_Init HAL_PPP/PPPP_MspInit 而且HAL_PPP/PPPP_MspInit函数的defination前面还会有__weak关键字 上面的PPP/PPPP代表常见外设的名称为…

【css】使用float实现水平导航栏

该实例使用float 浮动实现元素浮动在水平方向&#xff0c;从而实现水平导航栏效果。 overflow: hidden&#xff1a;当不给父级元素设置高度的时候&#xff0c;其内部元素浮动后会导致下面的元素顶上去&#xff0c;这是因为子元素浮动后&#xff0c;子元素脱离标准流&#xff0…

组合总和——力扣39

文章目录 题目描述回溯 题目描述 回溯 class Solution { public:vector<vector<int>> res;vector<int> seq; void dfs(vector<int>& nums, int pos, int target){if(target0){res.emplace_back(seq);return;}if(posnums.size()){return;}//直接跳过…

Python源码编译时碰到的问题:fatal error LNK1104: cannot open file libffi-7.lib

因为工作原因需要对python源码进行调试&#xff0c;所以Github上拉下来的cpython源码&#xff0c;编译一切顺利&#xff0c;除了一个报告说 LNK1104&#xff1a;无法打开libffi-7.lib 因为这些externals库是通过&#xff1a;PCbuild\get_externals.bat下载下来的&#xff0c;…

Java实现十大经典排序算法之快速排序

0 算法简介 快速排序是一种高效率排序算法&#xff0c;它是对冒泡排序的一种改进&#xff0c;它也是一种不稳定排序算法。快速排序的核心是比较、交换和递归。 在待排序数组中指定一个基准元素pivot&#xff08;一般选取数组首元素&#xff09;&#xff0c;使得数组排序之后基…

uniapp 使用iconfont

问题描述&#xff1a;在开发过程中会遇到使用自定义icon的情况&#xff0c;在uniapp项目中使用iconfont步骤如下。 问题解决 步骤一&#xff1a; 打开iconfont网址------我的项目-----下载至本地 下载成功的文件内容&#xff1a; 步骤二&#xff1a; 以管理员身份运行终端&am…

Linux的基本指令(2)

指令1&#xff1a;man 作用&#xff1a;可以查询linux指令语法内容。 格式&#xff1a; man 指令 安装man指令&#xff1a; yum install -y man-pages 例如&#xff1a; 查询 指令 ls 的语法内容。 man ls 查询 fork 指令的语法内容。 man fork 在man中存在9个手册&…

华为OD面试记录

The experience of applying for software test engineer(Dispatcher) 记录保存 招聘岗位: 测试工程师 Base:西安 华为面试流程如下&#xff1a; 流程名内容机试三题,总分400分,最后一道题200分人力资源面试询问私人问题&#xff0c;不谈薪资一面技术面二面技术面主管问项目…

根据Pytorch源码实现的 ResNet18

一&#xff0c;类模块定义: import torch import torch.nn as nn import torch.nn.functional as F from torch import Tensorclass ResBlock(nn.Module):def __init__(self, inchannel, outchannel, stride1) -> None:super(ResBlock, self).__init__()# 这里定义了残差块…