题目描述
数组异或和的定义:把数组中所有的数异或起来得到的值。给定一个整型数组arr,其中可能有正、有负,有零,求其中子数组的最大异或和。
输入描述:
输出包含两行,第一行一个整数n,代表数组arr长度,第二个n个整数,代表数组arr。
输出描述:
输出一个整数,代表其中子数组的最大异或和。
示例1
输入
4
3 -28 -29 2
输出
7
说明
{-28,-29}这个子数组的异或和为7,是所有子数组中最大的
解法一:超时
另外用BufferedReader读数据报越界
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args)throws Exception{
Scanner in = new Scanner(System.in);
int n = in.nextInt();
// String[] seqStrArr = in.readLine().split(" ");
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = in.nextInt();
}
System.out.println(getRes(arr));
}
public static int getRes(int[] arr){
if(arr==null||arr.length==0){
return 0;
}
int[] eor=new int[arr.length];
eor[0]=arr[0];
//生成eor数组
for(int i=1;i<arr.length;i++){
eor[i]=eor[i-1]^arr[i];
}
int max=Integer.MIN_VALUE;
for(int j=0;j<arr.length;j++){
//j结尾
for(int i=0;i<=j;i++){
max=Math.max(max,i==0?eor[j]:eor[j]^eor[i-1]);
}
}
return max;
}
}
解法二:利用字典树
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args)throws Exception{
Scanner in = new Scanner(System.in);
int n = in.nextInt();
// String[] seqStrArr = in.readLine().split(" ");
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = in.nextInt();
}
System.out.println(getRes(arr));
}
public static int getRes(int[] arr){
if(arr==null||arr.length==0) return 0;
Trie root = new Trie();
root.add(0);
int max = Integer.MIN_VALUE;
int pre = 0;
for(int i=0;i<arr.length;i++){
pre = pre^arr[i];
max = Math.max(root.getMax(pre),max);
root.add(pre);
}
return max;
}
}
class TrieNode{
public TrieNode[] map = new TrieNode[2];
}
class Trie{
private TrieNode root = new TrieNode();
//构建字典树
public void add(int num){
TrieNode node = root;
for(int i=31;i>=0;i--){
int path = ((num>>i)&1);
if(node.map[path]==null){
node.map[path] = new TrieNode();
}
node = node.map[path];
}
}
//求此时最优解
public int getMax(int val) {
TrieNode curNode = root;
int path = 0;
// 最佳路径为哪条
int best = 0;
int res = 0;
// val在前缀树中行进,一位一位地处理,得到最大异或和
for (int move = 31; move >= 0; move--) {
// val中该处理的那一位
path = (val >> move) & 1;
// 前缀树中理想最佳路径
best = move == 31 ? path : (path ^ 1);
// 前缀树中实际最佳路径,即res的二进制表示中这一位该取何值
best = curNode.map[best] != null ? best : (best ^ 1);
// 用或操作收集每一位产生的结果
res |= (path ^ best) << move;
curNode = curNode.map[best];
}
return res;
}
}