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. 与数组中元素的最大异或值(字典树)