1. 程式人生 > >陣列中兩個數異或求最大值

陣列中兩個數異或求最大值

特別說明:本文轉載自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;  
         
    }