leetcode 421. Maximum XOR of Two Numbers in an Array
来源:互联网 发布:文言文辞职信走红网络 编辑:程序博客网 时间:2024/05/23 02:04
本题也是一个经典问题,流行的解法有两种,其中一种使用了字典树(Trie Tree)的数据结构,这种数据结构有很多引申的用途,一些经典面试题中也会用到,比如腾讯的QQ号查找算法实现,归属地算法等,都是字典树的典型应用(关于QQ号的查询有人文章里提到使用二叉查找的方式,个人觉得并没有字典树的方式快),因此会重点说明字典树的AC解。
题目描述
Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231.
Find the maximum result of ai XOR aj, where 0 ≤ i, j < n.
Could you do this in O(n) runtime?
解题思路
题目说的很清楚,找出一个非空数组的任意两个数的异或最大值,要求O(n)时间复杂度。
关于字典树:字典树的基本结构在网上有很多介绍,这里不做解释,字典树的基本思想就是空间换时间。
关于异或:这类型的题目遇到很多了,基本运算规则就是位运算了,对于一个给定的数组,数组的每个数都是确定的值,因此可以很容易构建出关于这个数组的二进制表达数的字典树,字典树的根节点不保存数据,因此从树的第一层到最后一层,分别对应二进制的最高位到最低位,这样一颗对应于原数组的字典树就创建出来了。
查询过程:对于数组中的每个数,都执行一次查询过程,找到的最大值即为所求。
代码实现(C++11):
1.字典树结构:
struct Trie;struct Trie { Trie* next[2]; bool isExist = false; int num = 0; Trie() { next[0] = nullptr; next[1] = nullptr; isExist = false; num = 0; }};
2.建树和搜索:
int findMaximumXOR(vector<int>& nums) { Trie* root; root = new Trie(); // so we create the trie tree for(auto &val:nums) { auto temp = root; for(int i = 31;i>=0;--i) { int t = (val>>i)&1; if(temp->next[t]==nullptr) { temp->next[t] = new Trie(); } temp = temp->next[t]; } temp->isExist = true; } //we search from the top root int maxVal = -1; for(auto &val:nums) { int tempMax = 0; auto temp = root; for(int i = 31; i>=0;--i) { int t = (val>>i)&1; if(temp->next[t^1]!=nullptr) { tempMax+=(1<<i); temp = temp->next[t^1]; }else { temp = temp->next[t&1]; } } maxVal = max(maxVal,tempMax); } return maxVal; }
第二种解法
让我们再次回到题目描述,我们要求数组中任意两个数异或的最大值,不考虑字典树的情况下,这确实是个令人头疼的问题,但是我们可以换种角度考虑问题,既然我们知道异或是按位进行,那么不管是什么样的数异或,他们的最大值不会超过2的31次方,也就是说即使我们从最高位开始计算,也只需要循环32次而已,这就给了我们一种思路,从最高位开始,我们假设有两个数的异或在该位上为1,而对于异或操作,有公式
1. a1^a2 = max
2. a1^a2^a2 = a1,故有
3. a1 = max^a2
也就是说,如果存在这样的max,我们可以通过公式3得到一个存在于数组中的数,如果不存在,则该数不存在于数组中,max中该位自然为0,在代码实现中,我们使用了位操作运算中经常使用的mask来表示已经操作过的位(数组中的所有数),因为可能存在的不同数在某一位上的重复位,我们使用set数据结构存储所有已访问过当前位的数,并通过公式3来做判断。具体的代码如下(C++ 11):
int solution(vector<int>& nums) {int mask = 0,max = 0;set<int> mySet;for(int i = 31;i>=0;--i){ //mask first mask = mask|1<<i; for(auto&val:nums) { mySet.insert(val&mask); } auto temp = max|1<<i; for(auto &val:mySet) { if(mySet.find(val^temp)!=mySet.end()){ max = temp; break; } } mySet.clear();}return max;}
两种方法各有优势,但大体思路是一致的,就代码量来看,方法2的代码更少且更容易理解,但是本题引申出的字典树是很重要的数据结构,需要掌握。
- [leetcode]421. Maximum XOR of Two Numbers in an Array
- 【LeetCode】 421. Maximum XOR of Two Numbers in an Array
- [leetcode]421. Maximum XOR of Two Numbers in an Array
- Leetcode-421. Maximum XOR of Two Numbers in an Array
- [LeetCode]421. Maximum XOR of Two Numbers in an Array
- leetcode 421. Maximum XOR of Two Numbers in an Array
- (LeetCode) 421. Maximum XOR of Two Numbers in an Array
- leetcode 421. Maximum XOR of Two Numbers in an Array
- LeetCode: 421. Maximum XOR of Two Numbers in an Array
- leetcode 421. Maximum XOR of Two Numbers in an Array
- 【LeetCode-421】Maximum XOR of Two Numbers in an Array
- LeetCode #421: Maximum XOR of Two Numbers in an Array
- Leetcode Maximum XOR of Two Numbers in an Array
- 【LeetCode】Maximum XOR of Two Numbers in an Array
- 421. Maximum XOR of Two Numbers in an Array详解
- 421. Maximum XOR of Two Numbers in an Array
- 421. Maximum XOR of Two Numbers in an Array
- 421. Maximum XOR of Two Numbers in an Array
- 玩转Excel系列-SUMIFS函数使用及实例
- 委托多播
- 第四天2017/03/31(下午2:结构体、数组)
- 类型转换
- 由FlexBox算法强力驱动的Weex布局引擎
- leetcode 421. Maximum XOR of Two Numbers in an Array
- java -封装性
- Andorid 调用H5时使用WebView的总结!
- Perfect Number
- linux 笔记
- Ora-01830 日期格式图片在转换整个输入字符串之前结束
- SpringMVC BindingResult验证框架Validation特殊用法
- MySQL连接失效问题
- Oracle常用的性能诊断语句