一天一大 leet (990. 等式方程的可满足性)
时间:2022-07-25
本文章向大家介绍一天一大 leet (990. 等式方程的可满足性),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目(难度:困难):
给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。
只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。
示例
- 示例 1
输入:["a==b","b!=a"]
输出:false
解释:如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。
- 示例 2
输出:["b==a","a==b"]
输入:true
解释:我们可以指定 a = 1 且 b = 1 以满足满足这两个方程。
- 示例 3
输入:["a==b","b==c","a==c"]
输出:true
- 示例 4
输入:["a==b","b!=c","c==a"]
输出:false
- 示例 5
输入:["c==c","b==d","x!=z"]
输出:true
提示
- 1 <= equations.length <= 500
- equations[i].length == 4
- equations[i][0] 和 equations[i][3] 是小写字母
- equations[i][1] 要么是 '=',要么是 '!'
- equations[i][2] 是 '='
抛砖引玉
- 提示中说 equations[i][3] 是小写字母则可以使用字母初始化一个长度伪 26 值不同是数组 parent
- 遍历等式运算,根据等式中出现的变量把对象的 parent 值置成相同
- 遍历不等式运算,如果不等式两边的字母对应的 parent 相同则返回 false
- 没有触发 false 这默认 true
/**
* @param {string[]} equations
* @return {boolean}
*/
var equationsPossible = function (equations) {
var parent = []
var len = equations.length
for (var i = 0; i < 26; i++) {
parent[i] = i
}
for (var index = 0; index < equations.length; index++) {
if (equations[index][1] === '=') {
var index1 = equations[index].charCodeAt(0) - 97
var index2 = equations[index].charCodeAt(3) - 97
union(parent, index1, index2)
}
}
for (var index = 0; index < equations.length; index++) {
if (equations[index][1] === '!') {
var index1 = equations[index].charCodeAt(0) - 97
var index2 = equations[index].charCodeAt(3) - 97
if (find(parent, index1) == find(parent, index2)) {
return false
}
}
}
return true
function union(parent, index1, index2) {
parent[find(parent, index1)] = find(parent, index2)
}
function find(parent, index) {
while (parent[index] != index) {
parent[index] = parent[parent[index]]
index = parent[index]
}
return index
}
}
官方答案
class Solution {
public boolean equationsPossible(String[] equations) {
int length = equations.length;
int[] parent = new int[26];
for (int i = 0; i < 26; i++) {
parent[i] = i;
}
for (String str : equations) {
if (str.charAt(1) == '=') {
int index1 = str.charAt(0) - 'a';
int index2 = str.charAt(3) - 'a';
union(parent, index1, index2);
}
}
for (String str : equations) {
if (str.charAt(1) == '!') {
int index1 = str.charAt(0) - 'a';
int index2 = str.charAt(3) - 'a';
if (find(parent, index1) == find(parent, index2)) {
return false;
}
}
}
return true;
}
public void union(int[] parent, int index1, int index2) {
parent[find(parent, index1)] = find(parent, index2);
}
public int find(int[] parent, int index) {
while (parent[index] != index) {
parent[index] = parent[parent[index]];
index = parent[index];
}
return index;
}
}
高手在民间
var equationsPossible = (equations) => {
const uf = new UnionFind(26)
for (const e of equations) {
// 将字母对应成数字
if (e[1] === '=') uf.union(e.charCodeAt(0) - 97, e.charCodeAt(3) - 97)
}
for (const e of equations) {
if (
e[1] == '!' &&
uf.findRoot(e.charCodeAt(0) - 97) == uf.findRoot(e.charCodeAt(3) - 97)
)
return false
}
return true
}
class UnionFind {
constructor(num) {
// num 顶点个数
this.roots = new Array(num)
this.ranks = new Array(num)
for (let i = 0; i < num; i++) {
this.roots[i] = -1
this.ranks[i] = 0
}
}
findRoot(x) {
// 找出顶点x的根节点
let x_root = x
while (this.roots[x_root] !== -1) {
// 一直找父节点,找到尽头
x_root = this.roots[x_root]
}
return x_root // 返回根节点
}
union(x, y) {
// 把顶点x和顶点y所在的集合合并到一起
let x_root = this.findRoot(x)
let y_root = this.findRoot(y)
if (x_root === y_root) return
let x_rank = this.ranks[x_root]
let y_rank = this.ranks[y_root]
if (x_rank < y_rank) {
// 谁高度大,谁就作为根节点
this.roots[x_root] = y_root
} else if (y_rank < x_rank) {
this.roots[y_root] = x_root
} else {
// 一样高,谁作为根节点都行
this.roots[y_root] = x_root
this.ranks[x_root]++
}
}
}
/**
* @param {string[]} equations
* @return {boolean}
*/
var equationsPossible = function (equations) {
let len = equations.length,
parent = [],
cnt = []
for (let i = 0; i < 26; i++) {
parent[i] = i
cnt[i] = 1
}
let find = function (x) {
while (parent[x] != x) {
// 进行路径压缩
parent[x] = parent[parent[x]]
x = parent[x]
}
return x
}
let union = function (a, b) {
let pa = find(a),
pb = find(b)
if (pa == pb) {
return
}
if (cnt[a] > cnt[b]) {
parent[pb] = pa
cnt[b] += cnt[a]
} else {
parent[pa] = pb
cnt[a] += cnt[b]
}
}
for (let i = 0; i < len; i++) {
if (equations[i].indexOf('==') != -1) {
union(
equations[i][0].charCodeAt() - 97,
equations[i][3].charCodeAt() - 97
)
}
}
for (let i = 0; i < len; i++) {
if (equations[i].indexOf('==') == -1) {
let t1 = equations[i][0].charCodeAt() - 97,
t2 = equations[i][3].charCodeAt() - 97
if (find(t1) == find(t2)) {
return false
}
}
}
return true
}
- [数据库基础]——快速浏览日期时间转换
- 【死磕Java并发】—- 深入分析CAS
- [SQLServer大对象]——FileTable从文件系统迁移文件
- [机器学习]-[数据预处理]-中心化 缩放 KNN(二)
- [数据清洗]-看上去一样的数字
- [数据清洗]- Pandas 清洗“脏”数据(三)
- [数据清洗]- Pandas 清洗“脏”数据(二)
- [数据清洗]-Pandas 清洗“脏”数据(一)
- [数据清洗]-混乱的邮编数据
- 10行代码,Python实现爬取淘宝/天猫评论
- 4.请求安全-- 结合使用的安全优势总结
- TensorFlow强化学习入门(4)——深度Q网络(DQN)及其扩展
- 3.请求安全-- 如何验证请求的唯一性
- 2.请求安全-- MD5的必要性以及实际应用场景
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Flutter中mixin的使用详解
- android实现圆形渐变进度条
- 如何在Android Studio下进行NDK开发
- flutter中build.gradle仓库的配置(解决外网下载速度过慢失败的问题)
- Android studio 实现随机位置画10个随机大小的五角星的代码
- 详解Android Studio实现用户登陆界面demo(xml实现)
- Flutter 实现进度条效果
- Android 侧边滑动关闭Activity的示例代码
- Flutter 系统是如何实现ExpansionPanelList的示例代码
- Flutter中如何使用WillPopScope的示例代码
- Android实现音乐播放进度条传递信息的两种方式(在service和activity中)
- Flutter 中 Dart的Mixin示例详解
- Android Studio 实现九宫格功能
- Android user版通过adb_enable开启adb 调试 不提示对话框的流程分析
- Android实现圆线按钮进度效果