LeetCode1707. 与数组中元素的最大异或值 (字典树)/ 990. 等式方程的可满足性(并查集)

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode1707. 与数组中元素的最大异或值 (字典树)/ 990. 等式方程的可满足性(并查集)相关的知识,希望对你有一定的参考价值。

1707. 与数组中元素的最大异或值

2021.5.23 每日一题,又是异或,今天准备参加人生第一次周赛哈哈

题目描述

给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 queries[i] = [xi, mi] 。

第 i 个查询的答案是 xi 和任何 nums 数组中不超过 mi 的元素按位异或(XOR)得到的最大值。换句话说,答案是 max(nums[j] XOR xi) ,其中所有 j 均满足 nums[j] <= mi 。如果 nums 中的所有元素都大于 mi,最终答案就是 -1 。

返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length 且 answer[i] 是第 i 个查询的答案。

 

示例 1:

输入:nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]]
输出:[3,3,7]
解释:
1) 0 和 1 是仅有的两个不超过 1 的整数。0 XOR 3 = 3 而 1 XOR 3 = 2 。二者中的更大值是 3 。
2) 1 XOR 2 = 3.
3) 5 XOR 2 = 7.

示例 2:

输入:nums = [5,2,4,6,6,3], queries = [[12,4],[8,1],[6,3]]
输出:[15,-1,5]

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

思路

看到求异或的最大值,就想到上周末,每日一题出的好像也是个求异或最大值题。然后就去看了一下那天写的。发现用的是字典树。
想了一下,觉得确实可以用字典树,但是没想到限制大小该怎么办

其实先排序,然后将数从小到大依次往字典树里面存(最大为mi),然后取当前最大值,是自己没好好想

另一个称为“在线查询”方法,就是在字典树的每个节点位置多存储一个变量,记录以当前节点为根节点的子树所记录元素的最小值。然后查询的时候,根据这个节点的最小值,判断是否能进入这个节点

class Solution {
    public int[] maximizeXor(int[] nums, int[][] queries) {
        //因为前不久有一道每日一题就是异或求最大值,用的是字典树
        //所以很自然而然的想到了字典树,但是没想到怎么处理限制mi

        //第一种方法:排序,将两个数组都排序,然后根据mi一个个往里面存
        Arrays.sort(nums);
        //因为最后返回需要按原查询数组的顺序返回,因此这里先把原顺序存储起来
        int lq = queries.length;
        int[][] newquery = new int[lq][3];
        //第三个维度存储原数组下标
        for(int i = 0; i < lq; i++){
            newquery[i][0] = queries[i][0];
            newquery[i][1] = queries[i][1];
            newquery[i][2] = i;
        }
        //从小到大排
        Arrays.sort(newquery, new Comparator<int[]>(){
            public int compare(int[] query1, int[] query2){
                return query1[1] - query2[1];
            }
        });

        Trie trie = new Trie();
        int index = 0;
        int[] res = new int[lq];
        for(int i = 0; i < lq; i++){
            int mi = newquery[i][1];
            //如果小于mi,就插入字典树中
            while(index < nums.length && nums[index] <= mi){
                trie.insert(nums[index]);
                index++;
            }
            if(index == 0)
                res[newquery[i][2]] = -1;
            else
                res[newquery[i][2]] = trie.findMax(newquery[i][0]);
        }
        return res;

    }
}

class Trie{
    Trie[] children = new Trie[2];

    public void insert(int x){
        Trie node = this;
        for(int i = 30; i >= 0; i--){
            int bit = (x >> i) & 1;
            if(node.children[bit] == null)
                node.children[bit] = new Trie();
            node = node.children[bit];
        }
    }

    public int findMax(int x){
        Trie node = this;
        int res = 0;
        for(int i = 30; i >= 0; i--){
            int bit = (x >> i) & 1;
            int find = 1 - bit;
            if(node.children[find] != null){
                node = node.children[find];
                res = res * 2 + 1;
            }else{
                node = node.children[bit];
                res = res * 2;
            }
        }
        return res;
    }
}

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

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

思路

今天是真有毒,好多次自己觉得代码完全没问题,但是一执行就是错,因为在宿舍做的,还没法Debug

今天学习内容是并查集,然后就想着趁这个机会去复习一下并查集
这个题呢,就是把等式两端的元素放在一个集合里,然后构建好并查集以后,去查询不等式两端的元素是否在一个集合中,如果在一个集合中,就与之前的等式矛盾了,返回false;如果没有矛盾的项,就返回true

在经过去年12月吧好像,一个并查集月的洗礼以后,经过五个月并查集还是能很快写出来,而且还能完全压缩,隔代压缩,按秩合并!!!
但是刚开始parents[px] = py写成py = parents[px] 了,一直报错,而且看了好几遍没看出来,有点烦有点烦!

class Solution {
    public boolean equationsPossible(String[] equations) {
        //2021.5.23再来复习一下并查集,马马虎虎写了一个
        int l = equations.length;
        UnionFind un = new UnionFind(26);
        for(int i = 0; i < l; i++){
            String s = equations[i];
            char x = s.charAt(0);
            char y = s.charAt(3);
            char z = s.charAt(1);
            if(z == '='){
                un.union(x - 'a', y - 'a');
            }
        }
        for(int i = 0; i < l; i++){
            String s = equations[i];
            char x = s.charAt(0);
            char y = s.charAt(3);
            char z = s.charAt(1);
            if(z == '!'){
                if(un.query(x - 'a', y - 'a'))
                    return false;
            }
        }
        return true;
    }
}

class UnionFind{
    int[] parents;
    int n;
    int[] rank;

    public UnionFind(int n){
        this.n = n;
        parents = new int[n];
        rank = new int[n];
        for(int i = 0; i < n; i++){
            parents[i] = i;
            rank[i] = 1;
        }
    }

    public void union(int x, int y){
        int px = find(x);
        int py = find(y);
        if(px != py){
            if(rank[x] < rank[y]){
                parents[px] = py;
            }else if(rank[x] > rank[y]){
                parents[py] = px;
            }else{
				parents[px] = py;
				rank[py]++;
			}     
        }
    }
	//完全压缩
    public int find(int x){
        if(x != parents[x]){
            parents[x] = find(parents[x]);
        }
        return parents[x];
    }
	//隔代压缩
	public int find(int x){
		while(x != parents[x]){
			parents[x] = parents[parents[x]];
			x = parents[x];
		}
		return x;
	}

    public boolean query(int x, int y){
        int px = find(x);
        int py = find(y);
        return px == py;
    }
}

以上是关于LeetCode1707. 与数组中元素的最大异或值 (字典树)/ 990. 等式方程的可满足性(并查集)的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode每日一题——1707. 与数组中元素的最大异或值(字典树)

1707. 与数组中元素的最大异或值

LeetCode﹝前缀树ி﹞最长单词键值映射最大异或值

[Leetcode421](python): 数组中两个数之间最大的异或值

数组中两个元素的最大异或

LeetCode 421. 数组中两个数的最大异或值