leetcode每日不做题
461. 汉明距离
852. 山脉数组的峰顶索引
374. 猜数字大小
278. 第一个错误的版本
474. 一和零
231. 2 的幂
342. 4的幂
1074. 元素和为目标值的子矩阵数量
477. 汉明距离总和
12. 整数转罗马数字
1190. 反转每对括号间的子串
692. 前K个高频单词
1738. 找出第 K 大的异或坐标值
1442. 形成两个异或相等数组的三元组数目
993. 二叉树的堂兄弟节点
421. 数组中两个数的最大异或值
13.罗马数字转整数
本文档使用 MrDoc 发布
-
+
首页
421. 数组中两个数的最大异或值
[力扣原题链接](https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/) ## 题目 给你一个整数数组 `nums` ,返回 `nums[i] XOR nums[j]` 的最大运算结果,其中 `0 ≤ i ≤ j < n` 。 进阶:你可以在 `O(n)` 的时间解决这个问题吗? **示例 1:** ``` 输入:nums = [3,10,5,25,2,8] 输出:28 解释:最大运算结果是 5 XOR 25 = 28. ``` **示例 2:** ``` 输入:nums = [0] 输出:0 ``` **示例 3:** ``` 输入:nums = [2,4] 输出:6 ``` **示例 4:** ``` 输入:nums = [8,10,2] 输出:10 ``` **示例 5:** ``` 输入:nums = [14,70,53,83,49,91,36,80,92,51,66,70] 输出:127 ``` **提示:** * `1 <= nums.length <= 2 * 104` * `0 <= nums[i] <= 231 - 1` ## 思路 使用二重循环枚举 `i` 和 `j`,计算所有数字两两异或的值并比较找出最大值,此方法简单但费时,会有超时的风险。 ## 代码 语言:Java ``` class Solution { public int findMaximumXOR(int[] nums) { // 同一个数异或等于0,所以数组长度为1时必返回0 if (nums.length <= 1) { return 0; } int max = 0; // 二重循环数组,两两异或并进行比较获得最大的异或结果 for (int i = 0; i < nums.length; i++) { for (int j = i + 1; j < nums.length; j++) { if((nums[i] ^ nums[j]) > max) { max = nums[i] ^ nums[j]; } } } return max; } } ``` ## 力扣官方代码 [题解链接](https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/solution/shu-zu-zhong-liang-ge-shu-de-zui-da-yi-h-n9m9/ "题解链接") 题外话:官方题解都是从二进制角度出发,有想过从这个角度对自己的代码进行优化,但不会 **1.哈希表法** ``` class Solution { // 最高位的二进制位编号为 30 static final int HIGH_BIT = 30; public int findMaximumXOR(int[] nums) { int x = 0; for (int k = HIGH_BIT; k >= 0; --k) { Set<Integer> seen = new HashSet<Integer>(); // 将所有的 pre^k(a_j) 放入哈希表中 for (int num : nums) { // 如果只想保留从最高位开始到第 k 个二进制位为止的部分 // 只需将其右移 k 位 seen.add(num >> k); } // 目前 x 包含从最高位开始到第 k+1 个二进制位为止的部分 // 我们将 x 的第 k 个二进制位置为 1,即为 x = x*2+1 int xNext = x * 2 + 1; boolean found = false; // 枚举 i for (int num : nums) { if (seen.contains(xNext ^ (num >> k))) { found = true; break; } } if (found) { x = xNext; } else { // 如果没有找到满足等式的 a_i 和 a_j,那么 x 的第 k 个二进制位只能为 0 // 即为 x = x*2 x = xNext - 1; } } return x; } } ``` **2.字典树** ``` class Solution { // 字典树的根节点 Trie root = new Trie(); // 最高位的二进制位编号为 30 static final int HIGH_BIT = 30; public int findMaximumXOR(int[] nums) { int n = nums.length; int x = 0; for (int i = 1; i < n; ++i) { // 将 nums[i-1] 放入字典树,此时 nums[0 .. i-1] 都在字典树中 add(nums[i - 1]); // 将 nums[i] 看作 ai,找出最大的 x 更新答案 x = Math.max(x, check(nums[i])); } return x; } public void add(int num) { Trie cur = root; for (int k = HIGH_BIT; k >= 0; --k) { int bit = (num >> k) & 1; if (bit == 0) { if (cur.left == null) { cur.left = new Trie(); } cur = cur.left; } else { if (cur.right == null) { cur.right = new Trie(); } cur = cur.right; } } } public int check(int num) { Trie cur = root; int x = 0; for (int k = HIGH_BIT; k >= 0; --k) { int bit = (num >> k) & 1; if (bit == 0) { // a_i 的第 k 个二进制位为 0,应当往表示 1 的子节点 right 走 if (cur.right != null) { cur = cur.right; x = x * 2 + 1; } else { cur = cur.left; x = x * 2; } } else { // a_i 的第 k 个二进制位为 1,应当往表示 0 的子节点 left 走 if (cur.left != null) { cur = cur.left; x = x * 2 + 1; } else { cur = cur.right; x = x * 2; } } } return x; } } class Trie { // 左子树指向表示 0 的子节点 Trie left = null; // 右子树指向表示 1 的子节点 Trie right = null; } ```
renyi567
2021年5月16日 15:19
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
阅读量
次
本站总访问量
次
本站访客数
人次
Markdown文件
分享
链接
类型
密码
更新密码