|
| 1 | +/* |
| 2 | + * @lc app=leetcode id=421 lang=javascript |
| 3 | + * |
| 4 | + * [421] Maximum XOR of Two Numbers in an Array |
| 5 | + */ |
| 6 | +/** |
| 7 | + * @param {number[]} nums |
| 8 | + * @return {number} |
| 9 | + */ |
| 10 | +const findMaximumXOR = function(nums) { |
| 11 | + let maxResult = 0 |
| 12 | + let mask = 0 |
| 13 | + /*The maxResult is a record of the largest XOR we got so far. if it's 11100 at i = 2, it means |
| 14 | + before we reach the last two bits, 11100 is the biggest XOR we have, and we're going to explore |
| 15 | + whether we can get another two '1's and put them into maxResult |
| 16 | + |
| 17 | + This is a greedy part, since we're looking for the largest XOR, we start |
| 18 | + from the very begining, aka, the 31st postition of bits. */ |
| 19 | + for (let i = 31; i >= 0; i--) { |
| 20 | + //The mask will grow like 100..000 , 110..000, 111..000, then 1111...111 |
| 21 | + //for each iteration, we only care about the left parts |
| 22 | + mask = mask | (1 << i) |
| 23 | + |
| 24 | + let set = new Set() |
| 25 | + for (let num of nums) { |
| 26 | + /* we only care about the left parts, for example, if i = 2, then we have |
| 27 | + {1100, 1000, 0100, 0000} from {1110, 1011, 0111, 0010}*/ |
| 28 | + let leftPartOfNum = num & mask |
| 29 | + set.add(leftPartOfNum) |
| 30 | + } |
| 31 | + |
| 32 | + // if i = 1 and before this iteration, the maxResult we have now is 1100, |
| 33 | + // my wish is the maxResult will grow to 1110, so I will try to find a candidate |
| 34 | + // which can give me the greedyTry; |
| 35 | + let greedyTry = maxResult | (1 << i) |
| 36 | + |
| 37 | + for (let leftPartOfNum of set) { |
| 38 | + //This is the most tricky part, coming from a fact that if a ^ b = c, then a ^ c = b; |
| 39 | + // now we have the 'c', which is greedyTry, and we have the 'a', which is leftPartOfNum |
| 40 | + // If we hope the formula a ^ b = c to be valid, then we need the b, |
| 41 | + // and to get b, we need a ^ c, if a ^ c exisited in our set, then we're good to go |
| 42 | + let anotherNum = leftPartOfNum ^ greedyTry |
| 43 | + if (set.has(anotherNum)) { |
| 44 | + maxResult = greedyTry |
| 45 | + break |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + // If unfortunately, we didn't get the greedyTry, we still have our max, |
| 50 | + // So after this iteration, the max will stay at 1100. |
| 51 | + } |
| 52 | + return maxResult |
| 53 | +} |
0 commit comments