leetcode Daily Challenge on September 16th, 2020.
Difficulty : Medium
Related Topics : Bit Manipulation、Trie
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?
Input: [3, 10, 5, 25, 2, 8] Output: 28 Explanation: The maximum result is 5 ^ 25 = 28.
- mine
- Java
Runtime: 440 ms, faster than 5.06%, Memory Usage: 47.3 MB, less than 51.42% of Java online submissions
// O(n^2)time // O(1)space public int findMaximumXOR(int[] nums) { int n = nums.length; int max = 0; int res = 0; for(int i = 0; i < n; i++){ for(int j = i + 1; j < n; j++){ res = Math.max(res, nums[i] ^ nums[j]); } } return res; }
- Java
- the most votes
Runtime: 40 ms, faster than 57.26%, Memory Usage: 42 MB, less than 64.53% of Java online submissions
// O(N)time // O(1)space public int findMaximumXOR(int[] nums) { int maxResult = 0; int mask = 0; /*The maxResult is a record of the largest XOR we got so far. if it's 11100 at i = 2, it means before we reach the last two bits, 11100 is the biggest XOR we have, and we're going to explore whether we can get another two '1's and put them into maxResult This is a greedy part, since we're looking for the largest XOR, we start from the very begining, aka, the 31st postition of bits. */ for (int i = 31; i >= 0; i--) { //The mask will grow like 100..000 , 110..000, 111..000, then 1111...111 //for each iteration, we only care about the left parts mask = mask | (1 << i); Set<Integer> set = new HashSet<>(); for (int num : nums) { /* we only care about the left parts, for example, if i = 2, then we have {1100, 1000, 0100, 0000} from {1110, 1011, 0111, 0010}*/ int leftPartOfNum = num & mask; set.add(leftPartOfNum); } // if i = 1 and before this iteration, the maxResult we have now is 1100, // my wish is the maxResult will grow to 1110, so I will try to find a candidate // which can give me the greedyTry; int greedyTry = maxResult | (1 << i); for (int leftPartOfNum : set) { //This is the most tricky part, coming from a fact that if a ^ b = c, then a ^ c = b; // now we have the 'c', which is greedyTry, and we have the 'a', which is leftPartOfNum // If we hope the formula a ^ b = c to be valid, then we need the b, // and to get b, we need a ^ c, if a ^ c exisited in our set, then we're good to go int anotherNum = leftPartOfNum ^ greedyTry; if (set.contains(anotherNum)) { maxResult = greedyTry; break; } } // If unfortunately, we didn't get the greedyTry, we still have our max, // So after this iteration, the max will stay at 1100. } return maxResult; }