陣列中兩個數異或求最大值
阿新 • • 發佈:2019-02-20
特別說明:本文轉載自lingen1949 大神的文章,按照個人理解增加了部分註釋,感謝大神提供思路。在此附上原文連結:
題目要求:
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?
Example:
Input: [3, 10, 5, 25, 2, 8] Output: 28 Explanation:The maximum result is 5 ^ 25 = 28.
思路一:
利用a ^ b = c,而a ^ b ^ b = a, 則 c ^ b = a.
int findMaximumXOR(vector<int>& nums) { if (nums.size() < 2) return 0; int maxNum = 0; int flag = 0; //本題關鍵在於,最終最大的異或結果一定是由所有數中,高位最先為1的數(也就是最大的數)參與得到的。 for (int i = 31; i >= 0; --i) {//從最大值maxNum最高位到最低位開始確定</span> set<int> hash; flag |= (1 << i); //利用flag取出每一個x的前n-i位,n為31 for (int x : nums) { hash.insert(flag & x); //將取出來的每一種前n-i位存入到集合中,以備接下來比較。 } int tmp = maxNum | (1 << i); //maxNum為上一次比較得出的前n-i位最大的數值,利用tmp嘗試,若緊鄰的下一位為1,是否有可能? for (int x : hash) { //此處用到了x1^tmp=x2,則x1^x2=tmp.原因:x1^tmp=x2,兩邊同時異或x1,則tmp=x1^x2. if (hash.find(x ^ tmp) != hash.end()) //如果存在,就說明有一個數的前n-i位與另一個數的前n-i位異或結果為該maxNum { maxNum = tmp; break; } } } return maxNum; }
思路二:
Tire樹,利用nums中的數構建tire樹,然後依次查詢陣列nums中數的異或最大值
struct Node{ Node * next[2]; Node() { next[0] = nullptr; next[1] = nullptr; } }; void buildTireTree(Node* root, int x) { for( int i = 31; i >= 0; --i ) { int flag = ( x & (1<<i) ) ? 1 : 0; if( root->next[flag] == nullptr ) { root->next[flag] = new Node(); } root = root->next[flag]; } } int findMaxXorInTire(Node* root, int x) { int result = 0; for( int i = 31; i >= 0; --i ) { int flag = ( x & ( 1<<i) )? 0: 1; if( root->next[flag] != nullptr ) { result |= (1<<i); root = root->next[flag]; } else root = root->next[1-flag]; } return result; } public: int findMaximumXOR(vector<int>& nums) { if( nums.size() < 2 ) return 0; Node head; for( int x: nums ) { buildTireTree( &head, x ); } int maxNum = 0;//INT_MIN; for( int x: nums ) { int m = findMaxXorInTire( &head, x ); maxNum = max( maxNum, m ); } return maxNum; }