LeetCode_Union Find_990. Satisfiability of Equality Equations 等式方程的可满足性【并查集,路径压缩,字符串处理】【java】【中等】

目录

一,题目描述

英文描述

中文描述

示例与说明

二,解题思路

三,AC代码

Java

四,解题过程

第一博


一,题目描述

英文描述

You are given an array of strings equations that represent relationships between variables where each string equations[i] is of length 4 and takes one of two different forms: "xi==yi" or "xi!=yi".Here, xi and yi are lowercase letters (not necessarily different) that represent one-letter variable names.

Return true if it is possible to assign integers to variable names so as to satisfy all the given equations, or false otherwise.

中文描述

给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。

只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。

示例与说明

 

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/satisfiability-of-equality-equations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二,解题思路

第一步,遍历所有等式,提取所有出现过的字符串变量,存放到set中去重;

第二步,根据第一步中提取出的变量,初始化并查集;

第三步,遍历所有含"=="的等式,完善并查集的联通关系;

第四步,遍历所有含"!="的等式,判断联通关系是否有冲突,有则返回false;

第五步,返回true。

注意:并查集应用中很容易出现的一种错误是,路径未完全压缩(同一棵树上节点的father不一定完全相同),然后直接用father[a] == father[b]来判断两节点是否联通。。。

解决方法如下:

三,AC代码

Java

class Solution {
    public boolean equationsPossible(String[] equations) {
        Map<String, String> father = new HashMap<>();
        Set<String> record = new HashSet<>();
        // 提取字符串变量
        for (int i = 0; i < equations.length; i++) {
            String s1 = equations[i].substring(0, 1);// 提取字符串[0,1)
            String s2 = equations[i].substring(3, 4);
            record.add(s1);
            record.add(s2);
        }
        // 初始化并查集
        for (String s : record) {
            father.put(s, s);
        }
        // 建立联通关系
        for (int i = 0; i < equations.length; i++) {
            if ("=".equals(equations[i].substring(1, 2))) {
                String s1 = equations[i].substring(0, 1);
                String s2 = equations[i].substring(3, 4);
                unionSet(father, s1, s2);
            }
        }
        for (int i = 0; i < equations.length; i++) {
            if ("!".equals(equations[i].substring(1, 2))) {
                String s1 = equations[i].substring(0, 1);
                String s2 = equations[i].substring(3, 4);
                String S1 = findFather(father, s1);// !!!这里需要重新对树进行路径压缩,确保树上所有子节点的father唯一
                String S2 = findFather(father, s2);// !!!这里需要重新对树进行路径压缩,确保树上所有子节点的father唯一
                if (S1.equals(S2)) return false;
            }
        }
        return true;
    }
    // 执行findather的同时会将树上的节点进行路径压缩
    public String findFather(Map<String, String> father, String s) {
        if (!father.get(s).equals(s)) {
            father.put(s, findFather(father, father.get(s)));// 直接put新的value会覆盖原先的
        }
        return father.get(s);
    }
    public void unionSet(Map<String, String> father, String a, String b) {
        String A = findFather(father, a);
        String B = findFather(father, b);
        if (!A.equals(B)) {
            father.put(A, B);
        }
    }
}

四,解题过程

第一博

字符串处理稍微有点麻烦,但是并查集的思路还是比较清晰的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值