leetcode 399-除法求值

在这里插入图片描述

法一:并查集

分析示例1:

  • a / b = 2.0 a/ b = 2.0 a/b=2.0,说明 a = 2 b a=2b a=2b a a a b b b在同一个集合中
  • b / c = 3.0 b/c=3.0 b/c=3.0,说明 b = 3 c b=3c b=3c b b b c c c在同一个集合中

a / c a/c a/c,可以把 a = 2 b , b = 3 c a=2b,b=3c a=2b,b=3c 依次代入,得到 a / c = 2 b c = 2 ⋅ 3 c c = 6.0 a/c=\frac{2b}{c}=\frac{2·3c}{c}=6.0 a/c=c2b=c23c=6.0

b / a b/a b/a,可以根据 a = 2 b a=2b a=2b 知道 b / a = 0.5 b/a=0.5 b/a=0.5,也可以把 b b b a a a 都转换成 c c c 的倍数, b / a = b 2 b = 3 c 6 c = 0.5 b/a=\frac{b}{2b}=\frac{3c}{6c}=0.5 b/a=2bb=6c3c=0.5

我们计算了两个结果,不难知道:可以将题目给出的 equations 中的两个变量所在集合进行**「合并」**,同在一个集合中的两个变量就可以通过某种方式计算出它们的比值。具体来说,可以把不同的变量的比值转换成相同变量的比值,然后再计算转换成相同变量以后的系数的比值,即为结果。统一了比较的标准,可以以 O ( 1 ) O(1) O(1) 的时间复杂度来完成计算。

如果两个变量不在一个集合中,返回 − 1.0 -1.0 1.0。并且根据题目的意思,如果两个变量中 至少有一个 变量没有出现在所有 equations 出现的字符集合中,也返回 − 1.0 −1.0 1.0

构建有向图

通过例1的分析,题目给出的 equationsvalues 可以表示成一个图,equations 中出现的变量就是图的顶点,「分子」与「分母」的比值可以表示成一个有向关系(因为「分子」和「分母」是有序的,不可以对换),并且这个图是一个带权图,values 就是对应的有向边的权值。

例 1 中给出的 equationsvalues 表示的「图形表示」、「数学表示」和「代码表示」如下表所示。

  • 其中 parent[a] = b 表示:结点 a 的(直接)父亲结点是 b
  • weight[a] = 2.0,即 weight[a] 表示结点 a 到它的 直接父亲结点 的有向边的权重
img

如何统一变量?

通过例1的分析,可以把 queries 中的不同变量转换成同一个变量,这样在计算 queries 的时候就可以用 O ( 1 ) O(1) O(1) 的时间复杂度计算出结果,在「并查集」的一个优化技巧中,「路径压缩」就恰好符合了这样的应用场景。

如下图所示:路径压缩前后,并查集所表示的两棵树形结构等价,路径压缩以后的树的高度为 2,查询性能最好。

image.png

由于有「路径压缩」的优化,两个在一个连通分量中的不同变量,它们分别到根节点的权值的比值就是要求的结果。

如何在「路径压缩」中维护权值变化?

如下图所示,在结点a 执行一次「查询」操作。路径压缩会先一层一层向上先找到根结点 d,然后依次把 cba 的父节点指向根节点 d

  • c 的父节点已经是根节点了,它的权值不用更改。
  • b 的父节点要修改成根节点,它的权值就是从当前节点到根节点经过的所有有向边的权值的乘积。
  • a 的父节点也要修改成根节点,但没必要把三条有向边的权值乘起来,可以直接用更新后的 bd 的权值乘以 ab 的权值。
image.png

如何在「合并」操作中维护权值的变化?

「合并」操作基于这样一个前提:将要合并的两棵树的高度最多为2,就是两棵树都必须要经过「路径压缩」。

例如:已知 a / b = 3.0 , d / c = 4.0 , a / d = 6.0 a/b=3.0,\ d/c=4.0,\ a/d=6.0 a/b=3.0, d/c=4.0, a/d=6.0,现在合并节点 ad 所在的集合,其实就是把 a 的根节点 b 指向 d 的根节点 c,那么如何计算 b 指向 c 的这条有向边的权重呢?

根据 a 经过 b 可以到达 ca 经过 d 也可以到达 c,因此两条路径上的有向边的权值的乘积必定相等。因此根据等式可求得 b / c = a d ⋅ d c a b b/c=\frac{\frac{a}{d}·\frac{d}{c}}{\frac{a}{b}} b/c=badacd

image.png

一个小细节

在合并以后,产生了一棵高度为 3 的树,那么我们在执行查询的时候,例如下图展示的绿色结点和黄色结点,绿色结点并不直接指向根结点,在计算这两个变量的比值的时候,计算边的权值的比值得到的结果是不对的。

image.png

但其实不用担心这个问题,并查集的「查询」操作会执行「路径压缩」,所以真正在计算两个变量的权值的时候,绿色结点已经指向了根结点,和黄色结点的根结点相同。因此可以用它们指向根结点的有向边的权值的比值作为两个变量的比值。

image.png

我们通过这个细节向大家强调:一边查询一边修改结点指向是并查集的特色

代码

#include <vector>
#include <unordered_map>
#include <string>
using namespace std;class UnionFind{										//并查集类
private:vector<int> parent;vector<double> weight;      						//指向父节点的权重public:UnionFind(int n){        							//初始化,节点指向自己,初始权重为1.0parent = vector<int>(n);weight = vector<double>(n);for(int i = 0; i < n; i++){parent[i] = i;weight[i] = 1.0;}}int find(int x){                                	//带路径压缩的查找if(x != parent[x]){				 				//x节点不为根节点int origin = parent[x];						//记录父节点parent[x] = find(parent[x]);				//递归向上查找父节点weight[x] *= weight[origin];				//将路径上的权重相乘}return parent[x];}void unite(int x, int y, double value){				//合并int rootX = find(x), rootY = find(y);			//查找过程中已经进行过路径压缩if(rootX == rootY)								//若在同一集合,直接返回return;parent[rootX] = rootY;							//合并操作weight[rootX] = weight[y] * value / weight[x];	//value=a/d,weight[y]=d/c,weight[x]=a/b}double isConnected(int x, int y){					//计算x/y的结果int rootX = find(x);int rootY = find(y);if(rootX == rootY)								//若为同一集合,则直接相除即为结果return weight[x] / weight[y];else											//若不为同一集合,说明问题中有未知变量return -1.0;}
};class Solution{
public:vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {int equationsSize = equations.size();UnionFind unionFind(2 * equationsSize);//第一步:预处理,将变量的值转换为数字(并查集),使得并查集的底层使用数组实现,方便编码unordered_map<string, int> hashMap(2 * equationsSize);int id = 0;for(int i = 0; i < equationsSize; i++){string var1 = equations[i][0];string var2 = equations[i][1];if(hashMap.count(var1) == 0){hashMap[var1] = id++;}if(hashMap.count(var2) == 0){hashMap[var2] = id++;}unionFind.unite(hashMap[var1], hashMap[var2], values[i]);	//将所有集合合并 var1/var2}//第二步:查询int queriesSize = queries.size();vector<double> res(queriesSize, -1.0);							//存储结果for(int i = 0; i < queriesSize; i++){string var1 = queries[i][0];string var2 = queries[i][1];if(hashMap.count(var1) && hashMap.count(var2)){				//变量在条件中出现,计算结果int id1 = hashMap[var1];int id2 = hashMap[var2];res[i] = unionFind.isConnected(id1, id2);}}return res;}
};

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

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

相关文章

微服务——ES实现自动补全

效果展示 在搜索框根据拼音首字母进行提示 拼音分词器 和IK中文分词器一样的用法&#xff0c;按照下面的顺序执行。 # 进入容器内部 docker exec -it elasticsearch /bin/bash# 在线下载并安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch…

【C++】红黑树的原理与实现

文章目录 一、引言 二、红黑树的概念与性质 2、1 红黑树的概念 2、2 红黑树的性质 三、红黑树的定义与实现 3、1 红黑树的定义 3、2 插入新节点 3、2、1 默认插入红色节点 3、3 插入情况分类 3、3、1 情况一&#xff08;根据颜色向上调整&#xff09; 3、3、2 情况二&#xff0…

AIGC技术到底是什么?为什么这么火热?

AIGC技术到底是什么&#xff1f;为什么这么火热&#xff1f; ALCG技术到底是什么&#xff1f;AIGC技术的发展史AIGC技术特点AIGC技术主要用途ALGC技术未来发展 ALCG技术到底是什么&#xff1f; AIGC&#xff08;Artificial Intelligence in Game Creation&#xff09;技术是指…

OpenLayers实战,OpenLayers实现气象台风飓风运动轨迹运动动画,可调台风旋转速度和运动速度,静态图片旋转动画

专栏目录: OpenLayers实战进阶专栏目录 前言 本章使用OpenLayers实现气象中常用的台风或者飓风运动轨迹动画,支持调整台风图标旋转速度和运动速度。 不同的台风可以设置不同的运动速度和旋转速度,也可以通过变量控制图片不旋转。 本章图片使用静态png图片,并非gif动态图。…

中间件多版本冲突的4种解决方案和我们的选择

背景 在小小的公司里面&#xff0c;挖呀挖呀挖。最近又挖到坑里去了。一个稳定运行多年的应用&#xff0c;需要在里面支持多个版本的中间件客户端&#xff1b;而多个版本的客户端在一个应用里运行时会有同名类冲突的矛盾。在经过询问chatGPT&#xff0c;百度&#xff0c;googl…

在Python中定义Main函数

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 许多编程语言都有一个特殊的函数&#xff0c;当操作系统开始运行程序时会自动执行该函数。 这个函数通常被命名为main()&#xff0c;并且依据语言标准具有特定的返回类型和参数。 另一方面&#xff0c;Python解释器从文件…

SQL-每日一题【1179. 重新格式化部门表】

题目 部门表 Department&#xff1a; 编写一个 SQL 查询来重新格式化表&#xff0c;使得新的表中有一个部门 id 列和一些对应 每个月 的收入&#xff08;revenue&#xff09;列。 查询结果格式如下面的示例所示&#xff1a; 解题思路 1.题目要求我们重新格式化表&#xff0c;…

Sentieon | 应用教程: 关于读段组的建议

介绍 本文档描述了使用Sentieon Genomics软件时&#xff0c;推荐使用RGID字段以最小化潜在问题的用法。 本文档能帮助您确定设置所使用的bam文件中RG标签的不同字段的最佳实践方法。 RG字段及其用法的详细描述 RG字段的详细描述 SAM格式规范http://samtools.github.io/hts-…

Android Studio实现刮刮卡效果

代码和刮刮乐图片参考网络 实现效果 MainActivity import android.app.Activity; import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentV…

教雅川学缠论06-中枢

本系列文章之前讲的内容都只有上升和下降两类趋势&#xff0c;并没有提及盘整&#xff0c;在缠论中&#xff0c;中枢这个新词汇用来定义盘整&#xff0c;中枢&#xff1a; 1.至少由5条线段&#xff08;或笔&#xff09;组成 2.中枢是有方向的&#xff0c;中枢左右两侧外面的线&…

【locust】使用locust + boomer实现对接口的压测

目录 背景 环境安装 脚本编写 master slave节点&#xff08;golang/boomer&#xff09; 问题 资料获取方法 背景 很早之前&#xff0c;考虑单机执行能力&#xff0c;使用locust做过公司短信网关的压测工作&#xff0c;后来发现了一个golang版本的locust&#xff0c;性能…

替换开源LDAP,某科技企业用宁盾目录统一身份,为业务敏捷提供支撑

客户介绍 某高科技企业成立于2015年&#xff0c;是一家深耕于大物流领域的人工智能公司&#xff0c;迄今为止已为全球16个国家和地区&#xff0c;120余家客户打造智能化升级体验&#xff0c;场景覆盖海陆空铁、工厂等货运物流领域。 该公司使用开源LDAP面临的挑战 挑战1 开源…

01《Detecting Software Attacks on Embedded IoT Devices》随笔

2023.08.05 今天读的是一篇博士论文 论文传送门&#xff1a;Detecting Software Attacks on Embedded IoT Devices 看了很长时间&#xff0c;发现有一百多页&#xff0c;没看完&#xff0c;没看到怎么实现的。 摘要 联网设备的增加使得嵌入式设备成为各种网络攻击的诱人目标&…

c#设计模式-创建型模式 之 工厂模式

前言&#xff1a; 工厂模式&#xff08;Factory Pattern&#xff09;是一种常用的对象创建型设计模式。该模式的主要思想是提供一个创建对象的接口&#xff08;也可以是抽象类、静态方法等&#xff09;&#xff0c;将实际创建对象的工作推迟到子类中进行。这样一来&#xff0c…

第一百二十四天学习记录:C++提高:STL-deque容器(上)(黑马教学视频)

deque容器 deque容器基本概念 功能&#xff1a; 双端数组&#xff0c;可以对头端进行插入删除操作 deque与vector区别 vector对于头部的插入删除效率低&#xff0c;数据量越大&#xff0c;效率越低 deque相对而言&#xff0c;对头部的插入删除速度比vector快 vector访问元素的…

cpu util margin,cpu freq margin

【cpufreq governor】cpu util 和 cpu margin怎么计算的_悟空明镜的博客-CSDN博客 cpu util margin&#xff0c;cpu freq margin 根据policy_util schedtune_margin 作为算力选对应的cpu cluster或调频

dubbo之整合SpringBoot

目录 zookeeper安装 1.拉取ZooKeeper镜像 2.新建文件夹 3.挂载本地文件夹并启动服务 4.查看容器 5.进入容器&#xff08;zookeeper&#xff09; Dubbo Admin安装 1.下载dubbo-admin 2.zip包解压 3.修改配置文件 4.打包项目 5.启动jar 6.访问 构建项目 api模块 1.创建…

24届近5年上海理工大学自动化考研院校分析

今天学姐给大家带来的是上海理工大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、上海理工大学 学校简介 上海理工大学&#xff08;University of Shanghai for Science and Technology&#xff09;是一所以工学为主&#xff0c;工学、理学、经济学、管理学、文…

php实现登录的例子

界面&#xff1a; 登录界面login.html代码&#xff1a; <!DOCUMENT html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"…

【word密码】word设置只读,如何取消?

Word文件打开之后发现是只读模式&#xff0c;那么我们如何取消word文档的只读模式呢&#xff1f;今天给大家介绍几种只读模式的取消方法。 属性只读 有些文件可能是在文件属性中添加了只读属性&#xff0c;这种情况&#xff0c;我们只需要点击文件&#xff0c;再次查看文件属…