2019.11.20 LeetCode 從零單刷個人筆記整理(持續更新)
github:https://github.com/ChopinXBP/LeetCode-Babel
如果想用o(n)的方法找到最大的異或值,根本思路是將n^2的遍歷計算轉換成32n的按位匹配。這題可以用兩種方法:
1.異或性質+貪心算法
異或的性質:如果 a ^ b = c 成立,那麼a ^ c = b 與 b ^ c = a 均成立。
從最高位開始遍歷按位確定result的可能值。模板mask從最高位至第i位爲全1,用於截取前綴。
用mask將數組中所有數的前綴放入哈希表中,在result高位確定的基礎上假設第i位爲1,若哈希表中存在prifix1使得prefix2 = prefix1 ^ value,說明存在value = prefix1 ^ prefix2,更新result。
2.前綴樹
根據數組元素構造一棵二叉前綴樹,結點值存在代表當前位上存在該數值。
利用trie對每一個數num找最大異或值curMax。從最高位開始深度遍歷,bit代表樹上該位的值(0/1),trie遍歷傾向於向相反值(bit1)走,若(bit1)存在則curMax該位更新爲1;反之向1走,curMax該位更新爲0。
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?
給定一個非空數組,數組中元素爲 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 。
找到 ai 和aj 最大的異或 (XOR) 運算結果,其中0 ≤ i, j < n 。
你能在O(n)的時間解決這個問題嗎?
示例:
輸入: [3, 10, 5, 25, 2, 8]
輸出: 28
解釋: 最大的結果是 5 ^ 25 = 28.
import java.util.HashSet;
/**
*
* 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.
* 給定一個非空數組,數組中元素爲 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 。
* 找到 ai 和aj 最大的異或 (XOR) 運算結果,其中0 ≤ i,j < n 。
*
*/
public class MaximumXOROfTwoNumbersInAnArray {
//異或性質+貪心算法
//異或的性質:如果 a ^ b = c 成立,那麼a ^ c = b 與 b ^ c = a 均成立。
public int findMaximumXOR(int[] nums) {
int result = 0;
int mask = 0;
//從最高位開始按位確定result的可能值
for(int i = 31; i >= 0; i--){
//mask從最高位至第i位爲全1,用於截取前綴,將數組中所有數的前綴放入哈希表中
mask |= (1 << i);
HashSet<Integer> set = new HashSet<>();
for(int num : nums){
set.add(num & mask);
}
//在result高位確定的基礎上假設第i位爲1
int temp = result | (1 << i);
for(Integer prefix : set){
//若哈希表中存在prifix1使得prefix2 = prefix1 ^ value,說明存在value = prefix1 ^ prefix2
if(set.contains(prefix ^ temp)){
result = temp;
break;
}
}
}
return result;
}
//前綴樹
public int findMaximumXOR2(int[] nums) {
if(nums == null || nums.length == 0){
return 0;
}
Trie trie = new Trie();
return trie.getMaxXORValue(nums);
}
private class TrieNode{
TrieNode[] children = new TrieNode[2];
}
private class Trie{
TrieNode root;
Trie(){
root = new TrieNode();
}
public void insert(int num){
TrieNode curNode = root;
for(int i = 31; i >= 0; i--){
int bit = (num >>> i) & 1;
if(curNode.children[bit] == null){
curNode.children[bit] = new TrieNode();
}
curNode = curNode.children[bit];
}
}
public int getMaxXORValue(int[] nums){
//根據數組元素構造一棵二叉前綴樹,結點值存在代表當前位上存在該數值
for(int num : nums){
insert(num);
}
int max = Integer.MIN_VALUE;
//利用trie對每一個數num找最大異或值curMax
for(int num : nums){
TrieNode curNode = root;
int curMax = 0;
//bit代表樹上該位的值(0/1),trie遍歷傾向於向相反值(bit^1)走,若(bit^1)存在則curMax該位更新爲1;反之向1走,curMax該位更新爲0
for(int i = 31; i >= 0; i--){
int bit = (num >>> i) & 1;
if(curNode.children[bit ^ 1] != null){
curMax |= (1 << i);
curNode = curNode.children[bit ^ 1];
}else {
curNode = curNode.children[bit];
}
}
max = curMax > max ? curMax : max;
}
return max;
}
}
}
#Coding一小時,Copying一秒鐘。留個言點個讚唄,謝謝你#