数组中两个元素异或求最大值

给一个整数数组,求数组中两个元素异或的最大值.


思路:naive的做法是两两异或求最大值,时间复杂度为O(n*n),但是还有一种O(n)的解法,利用字典树Trie来实现.

其思路是利用数组中的每个元素二进制表示形式建一棵树,我看到网上大多数解法都开了太大的数组空间,不知道为什么,但是我觉得没有必要.只要用现有的数组元素二进制值建一棵深度为33的树即可,从根到叶子结点的路径就代表了一个元素.然后再对数组中每一个元素取反之后到Trie中去搜索最大的异或值,为什么要取反呢?因为取反之后在查找Trie的时候如果当前匹配的话,那么就说明当前这一位异或之后是为1的,我们就可以继续沿着这个分支走下去.如果不匹配说明异或之后当前这位是为0,并且这个分支为空,所以我们只能走另外一个分支.时间复杂度为O(32*n),也就是O(n)

代码如下:

/*************************************************************************
	> File Name: XorMax.cpp
	> Author: Maoting Ren
	> Mail: [email protected]
	> Created Time: Wed 28 Sep 2016 02:42:22 AM EDT
 ************************************************************************/

#include
#include
#include
using namespace std;

struct Trie
{
    vector child;
    Trie(): child(vector(2, NULL)){}
};

void add(int x, Trie* root)
{
    for(int i = 31; i >= 0; i--)
    {
        int bit = (x>>i)&1;
        if(!root->child[bit]) root->child[bit] = new Trie();
        root = root->child[bit];
    }
}

int search(int x, Trie* root)
{
    int ans = 0;
    for(int i = 31; i >= 0; i--)
    {
        int bit = (x>>i)&1;
        ans = ans<<1;
        if(root->child[bit]) ans++, root = root->child[bit];
        else root = root->child[!bit];
    }    
    return ans;
}

int main()
{
    Trie *root = new Trie();
    vector vec{1, 2, 4, 8};
    for(int i = 0; i < (int)vec.size(); i++) add(vec[i], root);
    int ans = 0;
    for(int i = 0; i < (int)vec.size(); i++) 
        ans =  max(ans, search(~vec[i], root));
    cout << ans << endl;
    return 0;
}








你可能感兴趣的:(位运算,trie)