最大子数组VI-LintCode

204 篇文章 0 订阅

给出一个整数数组,找出异或值最大的子数组。
什么是异或:https://en.wikipedia.org/wiki/Exclusive_or

注意事项:
预期时间复杂度为O(n)

样例:
给出nums = [1, 2, 3, 4],返回 7,子数组[3, 4]有最大的异或值
给出nums = [8, 1, 2, 12, 7, 6],返回 15,子数组[1, 2, 12]有最大的异或值
给出nums = [4, 6],返回 6,子数组[6]有最大的异或值

思路:
Let’s say F(L,R) is XOR of subarray from L to R.
Here we use the property that F(L,R)=F(1,R) XOR F(1,L-1). How?
Let’s say our subarray with maximum XOR ended at position i. Now, we need to maximise F(L,i) ie. F(1,i) XOR F(1,L-1) where L<=i. Suppose, we inserted F(1,L-1) in our trie for all L<=i, then it’s just problem1.
参考子数组异或的思路主要说明一个方法,将F(L,R)表示为从L位置到R位置的子数组的异或,有这样的性质
F(L,R)=F(0,R)xorF(0,L1)
所以,对于终结在i位置的子数组,需要计算F(L,i)的最大值,即计算F(0,i)xorF(0,L-1)。将F(0,L-1)插入到字典树中,在进行查找。
为了方便理解,给出例子nums{8,1,2,12}
i=0,prefix=0^8=8,query(8),就是它本身;
i=1,prefix=8^1,query(8^1),此时8^1与0,8^1以及8异或找出最大值,8^1^8=1,相当于从0到i-1进行遍历;
i=2,prefix=8^1^2,query(8^1^2),8^1^2与0,8^1,8^1^2以及8异或取最大值,即求{2},{1,2}异或的最大值
…………

#ifndef C722_H
#define C722_H
#include<iostream>
#include<vector>
using namespace std;
class TrieNode{
public:
    int val;
    TrieNode *child[2];
    TrieNode(){
        this->val = 0;
        this->child[0] = this->child[1] = NULL;
    }
};
class Solution {
public:
    /*
    * @param : the array
    * @return: the max xor sum of the subarray in a given array
    */
    int maxXorSubarray(vector<int> &nums) {
        // write code here
        TrieNode *root = new TrieNode();
        insert(root, 0);
        int res = INT_MIN, prefix = 0;
        for (int i = 0; i < nums.size(); ++i)
        {
            prefix = prefix^nums[i];
            insert(root, prefix);
            res = maxVal(res, query(root, prefix));
        }
        return res;
    }
    //构建字典树,子节点的值只能为0或1,将prefix的二进制形式插入到字典树中
    void insert(TrieNode *root, int prefix)
    {
        TrieNode *node = root;
        for (int i = 31; i >= 0; --i)
        {
            bool value = prefix & (1 << i);
            if (node->child[value] == NULL)
                node->child[value] = new TrieNode();
            node = node->child[value];
        }
        node->val = prefix;
    }
    //查找与prefix异或的最大值,遍历prefix二进制的每一位,从高位开始,优先选择与
    //此位上的数不一样的节点,如果不存在,就选择剩下的节点
    int query(TrieNode *root, int prefix)
    {
        TrieNode *node = root;
        for (int i = 31; i >= 0; --i)
        {
            bool value = prefix & (1 << i);
            if (node->child[1 - value] != NULL)
                node = node->child[1 - value];
            else
                node = node->child[value];
        }
        return prefix ^ (node->val);
    }
    int maxVal(int a, int b)
    {
        return a > b ? a : b;
    }
};
#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值