990. 等式方程的可满足性

题目:

思路:

【1】并交集的方式

由于是只有26个小写字母,所以可以用int数组来表示
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
这就表示每个字母当前的指向父节点都会自己,值为 字符-'a'的值(如'a' - 'a' = 0)
对应字符串的变化

1)字符串:c==c (这种本身就是这样指向的,故不变)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]

2)字符串:f==b 
所以 先找 f 的父节点 5, b 的父节点 1
然后 parent[5] = 1; 合并父节点 ,那么就会出现 5->11->1
[0, 1, 2, 3, 4, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]

3)字符串:b==c
所以 先找 b 的父节点 1, c 的父节点 2
然后 parent[1] = 2; 合并父节点 ,那么就会出现 2->21->2
汇总的话就是 5->11->22->2
[0, 2, 2, 3, 4, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]

4)字符串:f==z
所以 先找z 的父节点 25 , f 的父节点 1 指向b,再由1找到 2 指向c(所以f变更指向直接指向c,省略b的指向)
[0, 2, 25, 3, 4, 2, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]

 

代码展示:

//时间0 ms 击败 100%
//内存39.5 MB 击败 87.17%
class Solution {
    // 查并交集的情况
    public boolean equationsPossible(String[] equations) {
        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) {
            // 这一步并不关键,因为他的主要作用是将层级差巨大的进行缩短
            // 如 f->b->c ,直接变为 f->c,这种形式,用于缩短查找,但没有也不影响结果
            parent[index] = parent[parent[index]];
            index = parent[index];
        }
        return index;
    }
}

 

posted @ 2023-08-22 15:26  忧愁的chafry  阅读(13)  评论(0编辑  收藏  举报