Monday 2 September 2013

MAX XOR


/*    
    *  Given an array A of unsigned 32-bit ints, choose two in-bounds indices i, j so as to  maximize the value of A[i] ^ A[j], where ^ is the bitwise XOR (exclusive OR) operator. 
    *  If  there are multiple possible answers, print any one.
    *  Example Input:
    *  4 2 0 13 49
    *  Output:
    *  3 4
    *  Explanation: 13 ^ 49 is 60, 13 and 49 are positioned at indexes 3 and 4. Printing "4 3" would have been equally valid.
    *  Solution Guidance:
    *  Let k be the bit width (maximum number of bits) of the primitive.
    *  Easy: O(arr.length^2) time, O(1) space.
    *  Hard: Sub-quadratic complexity. An O(k*arr.length) time algorithm is possible. It is OK to use some extra space.
*/
 
#include <iostream>
using namespace std;
 
class node
{
    int val;
    bool isLeaf;
    node *left;
    node *right;
    
    public: 
    
    node()
    {
        val = 0;
        isLeaf = false;
        left = NULL;
        right = NULL;
    }
    
    void setVal(int n)
    {
        val = n;
    }
    
    int getVal()
    {
        return val;
    }
    
    void setLeftChild(node *ptr)
    {
        left = ptr;
    }
    
    void setRightChild(node *ptr)
    {
        right = ptr;
    }
    
    node* getLeftChild()
    {
        return left;
    }
    
    node* getRightChild()
    {
        return right;
    }
    
    void setIsLeaf(bool b)
    {
        isLeaf = b;
    }
    
    bool getIsLeaf()
    {
        return isLeaf;
    }
};
 
 
class Tree
{
    node *root;
    int heightOfTree ;
    public: 
    
    Tree()
    {
        root = new node();
        root->setVal(99);
        heightOfTree = 31;
    }
    
    int getMSBPosition()
    {
        return 0;
    }
    
    void insertNode(node* ptr, int n, int pos)
    {
        if(pos>=0)
        {
            int getBit = (1<<pos) & n;
            node* newNode;
            if(getBit)
            {
                if(ptr->getRightChild() == NULL)
                {
                    newNode = new node();
                    newNode->setVal(1);
                    ptr->setRightChild(newNode);
                }
                if(pos == 0)
                {
                    node* leafNode = new node();
                    newNode->setIsLeaf(true);
                    leafNode->setVal(n);
                    newNode->setLeftChild(leafNode);
                }
                else
                    insertNode(ptr->getRightChild(),n,pos-1);
            }
            else
            {
                if(ptr->getLeftChild() == NULL)
                {
                    newNode = new node();
                    newNode->setVal(0);
                    ptr->setLeftChild(newNode);
                }
                if(pos == 0)
                {
                    node* leafNode = new node();
                    leafNode->setVal(n);
                    newNode->setIsLeaf(true);
                    newNode->setLeftChild(leafNode);
                }
                else
                    insertNode(ptr->getLeftChild(),n,pos-1);
            }
        }
    }
    
    void insert(int n)
    {
        insertNode(root,n,heightOfTree);
    }
    
    int findMax(node* ptr1, node* ptr2)
    {
        if(ptr1->getIsLeaf() == false)
        {
            int n01 = 0;
            int n10 = 0;
            bool pathTaken = false;
            if(ptr1->getLeftChild() != NULL && ptr2->getRightChild() != NULL)
            {
                n01 = findMax(ptr1->getLeftChild(),ptr2->getRightChild());                
                pathTaken = true;
            }
            if(ptr1->getRightChild() != NULL && ptr2->getLeftChild() != NULL)
            {
                n10 = findMax(ptr1->getRightChild(),ptr2->getLeftChild());
                pathTaken = true;
            }
            if(!pathTaken)
            {
                if(ptr1->getLeftChild() && ptr2->getLeftChild())
                    n01 = findMax(ptr1->getLeftChild(),ptr2->getLeftChild());
                else
                    n10 = findMax(ptr1->getRightChild(),ptr2->getRightChild());
            }
            return n01>n10?n01 : n10;
        }
        else
        {
            return ptr1->getLeftChild()->getVal() ^ ptr2->getLeftChild()->getVal();
        }
    }
    int findMaxValue()
    {
        return findMax(root,root);
    }
    
};
 
int maxValue(int *arr,int n)
{
    int max = 0;
    for(int i=0; i<n-1; i++)
    {
        for(int j=0; j<n; j++)
        {
            if(max < (arr[i]^arr[j]))
                max = (arr[i]^arr[j]);
        }
    }
    return max;
}
 
int main()
{
    int numberOfElements;
    cout<<"\nNUMBER OF ELEMENTS : ";
    cin>>numberOfElements;
    Tree t ;
    int *arr = new int[numberOfElements];
    for(int i=0; i<numberOfElements;i++)
    {
        cin>>arr[i];
        t.insert(arr[i]);
    }
    cout<<"\nEASY = "<<maxValue(arr,numberOfElements);
    cout<<"\nHARD = "<<t.findMaxValue();
}

5 comments:

  1. The above solution implements the hard method of solving the problem.

    For simplicity consider k = 8.
    Binary Representation of 4 : 00000100
    Binary Representation of 2 : 00000010
    Binary Representation of 0 : 00000000
    Binary Representation of 13: 00001101
    Binary Representation of 49: 00110001

    To find maximum XOR result start from MSb (Most significant bit of each number).
    Bit-7 = 0 for all so result = 0.
    Bit-6 = 0 for all so result = 0.
    Bit-5 = 1 for 49 consider all other numbers in which Bit-5 = 0 inorder to get max xor output.
    Group-A = 49 and Group-B = 4,2,0,13,49.
    Bit-4 = 1 for 49 and zero for all others so Group-A = 49 and Group-B=4,2,0,13,49.
    Bit-3 = 0 for 49 and zero for all in Group-B except 13.
    Group-A = 49 and only 13 left in Group-B so result = 49 xor 13.

    This can be achieved by using TRIE data structure.
    A node in TRIE represents one bit.
    So every node can have atmost 2 nodes, left and right.
    Next node added to left of current node if next bit = 0.
    Next node added to right of current node if next bit = 1.

    The MSb (Most significant bit) is considered to be the root node.
    we are considering all positive numbers only so root node will always be 0 as sign bit = 0 for non -ve integers.

    Follow path from root to leaf nodes and try to take different paths.
    1. Start traversing tree down (root to leaf).
    2. If current node has only left/right element then take left/right path.
    3. If current node has both left and right elements then take left and right path and set current bit in result.
    Step-3 ensures we get maximum xor result.
    4. Repeat steps 1 to 3 until leaf nodes are reached.

    Result variable now gives maximum xor value.

    ReplyDelete
  2. hey, this is really helpful. After looking this i tried to findout the maximum AND in an Array . I wrote he code but wrong answer coming. You will surely catch what i am doing wrong. Please look once. Code is written here
    http://ideone.com/AO3DZI

    ReplyDelete
  3. Hi
    I guess you pasted wrong link, the code will not compile.

    ReplyDelete
  4. is there any way to find length of the subset that has Max XOR ?

    ReplyDelete
  5. is there any way to find length of the subset that has Max XOR ?

    ReplyDelete