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.mzph.cn/news/30332.shtml

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

相关文章

24届近5年重庆邮电大学自动化考研院校分析

今天给大家带来的是重庆邮电大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、重庆邮电大学 学校简介 重庆邮电大学简称"重邮"&#xff0c;坐落于直辖市-重庆市&#xff0c;入选国家"中西部高校基础能力建设工程”、国家“卓越工程师教育培养计划…

c51单片机16个按键密码锁源代码(富proteus电路图)

注意了&#xff1a;这个代码你是没法直接运行的&#xff0c;但是如果你看得懂&#xff0c;随便改一改不超过1分钟就可以用 #include "reg51.h" #include "myheader.h" void displayNumber(unsigned char num) {if(num1){P10XFF;P10P11P14P15P160;}else if…

PyCharm新手入门指南

安装好Pycharm后&#xff0c;就可以开始编写第一个函数&#xff1a;Hello World啦~我们就先来学习一些基本的操作&#xff0c;主要包含新建Python文件&#xff0c;运行代码&#xff0c;查看结果等等。 文章主要包含五个部分&#xff1a; 一、界面介绍 主要分为菜单栏、项目目录…

开发工具Eclipse的使用之导入项目(import)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Eclipse使用的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.导读 二.详细操作步骤 1.右击项…

吐血整理,Python接口自动化测试-接口关联依赖处理(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 场景说明 在面试…

cpolar的基础使用方法

如何使用cpolar内网穿透&#xff1f; 文章目录 如何使用cpolar内网穿透&#xff1f;前言1. 在群辉NAS系统下安装cpolar套件2. 管理隧道列表3. 创建固定数据隧道 前言 群晖作为大容量存储系统&#xff0c;既可以作为个人的私有存储设备&#xff0c;也可以放在小型企业中作为数据…

基于微信小程序的传染病酒店隔离平台设计与实现(Java+spring boot+MySQL+微信小程序)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于微信小程序的传染病酒店隔离平台设计与实现&#xff08;Javaspring bootMySQL微信小程序&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;…

回归决策树模拟sin函数

# -*-coding:utf-8-*- import numpy as np from sklearn import tree import matplotlib.pyplot as pltplt.switch_backend("TkAgg") # 创建了一个随机数生成器对象 rng rngnp.random.RandomState(1) print("rng",rng) #5*rng.rand(80,1)生成一个80行、1列…

clion run qt 问题汇总

一、Error copying file “D:/soft/QT/5.15.2/mingw81_64/bin/Qt5Cored.dll” to “D:/work/Ccode/qtproject/cmake-build-debug-qtmingw”.报错 查看路径下确实没有Qt5Cored.dll&#xff0c;只有Qt5Core.dll 注释掉cmakelist中的这三行 重新执行后成功 二、使用CLion编辑u…

【学习】若依源码(前后端分离版)之 “ 分页以及查询的功能实现”

大型纪录片&#xff1a;学习若依源码&#xff08;前后端分离版&#xff09;之 “ 分页以及查询的功能实现” 前端部分后端部分结语 包括代码生成也好&#xff0c;最原始的系统也好&#xff0c;若依里每个页面只要有数据&#xff0c;基本上就有分页的功能&#xff0c;所以理解分…

机器学习实战2决策树算法

文章目录 决策树算法核心是要解决两个的关键问题sklearn中的决策树模型sklearn建模步骤分类树Criterionrandom_state && splitter剪枝参数max_depthmin_samples_leaf&&min_samples_splitmax_features&&min_impurity_decrease确认最优剪枝参数目标权重参…

VR全景智慧文旅,用科技助力旅游业振兴

引言&#xff1a; 近年来&#xff0c;科技的迅猛发展将我们带入一个全新的数字化时代&#xff0c;而虚拟现实&#xff08;Virtual Reality&#xff0c;简称VR&#xff09;技术则以其令人惊叹的全新方式&#xff0c;影响着各个领域。其中&#xff0c;旅游业作为人们探索世界、体…

Camunda 7.x 系列【12】创建流程引擎

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 2.7.9 本系列Camunda 版本 7.19.0 源码地址:https://gitee.com/pearl-organization/camunda-study-demo 文章目录 1. ProcessEngine2. 创建流程引擎2.1 Java API2.2 XML 配置2.3 Spring2.4 Spring Boot1. Pr…

【2.1】Java微服务:详解Hystrix

✅作者简介&#xff1a;大家好&#xff0c;我是 Meteors., 向往着更加简洁高效的代码写法与编程方式&#xff0c;持续分享Java技术内容。 &#x1f34e;个人主页&#xff1a;Meteors.的博客 &#x1f49e;当前专栏&#xff1a; Java微服务 ✨特色专栏&#xff1a; 知识分享 &am…

VGG16模型详解

VGG16模型详解 0、VGG16介绍 VGG16是一种深度卷积神经网络&#xff0c;由牛津大学的研究团队于2014年开发。 VGG16在2014年的ImageNet Large Scale Visual Recognition Challenge (ILSVRC) 竞赛中取得了显著的成绩。它在图像分类任务中获得了当年的第二名&#xff0c;其准确…

matplotlib 笔记 plt.grid

用于添加网格线 主要参数 visible 布尔值&#xff0c;True表示画网格 which表示要显示的刻度线类型&#xff0c;可以是 major&#xff08;主刻度&#xff09;或 minor&#xff08;次刻度&#xff09;&#xff0c;或者同时显示&#xff08;both&#xff09;alpha 透明度 …

音视频--视频数据传输

参考文献 H264码流RTP封装方式详解&#xff1a;https://blog.csdn.net/water1209/article/details/126019272H264视频传输、编解码----RTP协议对H264数据帧拆包、打包、解包过程&#xff1a; https://blog.csdn.net/wujian946110509/article/details/79129338H264之NALU解析&a…

【Redis】初学Redis

目录 使用Redisyum安装redis启动redis操作redis设置远程连接 Redis路线Redis 使用Redis yum安装redis 使用命令&#xff0c;直接将Redis安装到linux服务器&#xff1a; yum -y install redis启动redis redis-server /etc/redis.conf &操作redis redis-cli设置远程连接…

Shopee虾皮买家号注册时需要注意什么问题

虾皮是一家在线购物平台&#xff0c;如果您打算在虾皮上注册一个买家账号&#xff0c;以下是一些需要注意的问题&#xff1a; 账号安全&#xff1a;确保您选择一个安全的密码&#xff0c;并定期更改密码&#xff0c;以保护您的账号免受未经授权的访问。 个人信息&#xff1a;…

网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(四)对战模块

网页版Java&#xff08;Spring/Spring Boot/Spring MVC&#xff09;五子棋项目&#xff08;四&#xff09;对战模块 一、约定前后端交互接口1. 建立连接接口2. 针对落子的请求和响应 二、实现前端页面三、实现后端1. 当用户进入房间&#xff0c;更新用户状态 OnlineUserManager…