You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class06;
public class Code01_MaxXOR {
// O(N^2)
public static int maxXorSubarray1(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
// 准备一个前缀异或和数组eor
// eor[i] = arr[0...i]的异或结果
int[] eor = new int[arr.length];
eor[0] = arr[0];
// 生成eor数组eor[i]代表arr[0..i]的异或和
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++) {
for (int i = 0; i <= j; i++) { // 依次尝试arr[0..j]、arr[1..j]..arr[i..j]..arr[j..j]
max = Math.max(max, i == 0 ? eor[j] : eor[j] ^ eor[i - 1]);
}
}
return max;
}
// 前缀树的Node结构
// nexts[0] -> 0方向的路
// nexts[1] -> 1方向的路
// nexts[0] == null 0方向上没路
// nexts[0] != null 0方向有路可以跳下一个节点
// nexts[1] == null 1方向上没路
// nexts[1] != null 1方向有路可以跳下一个节点
public static class Node {
public Node[] nexts = new Node[2];
}
// 基于本题,定制前缀树的实现
public static class NumTrie {
// 头节点
public Node head = new Node();
public void add(int newNum) {
Node cur = head;
for (int move = 31; move >= 0; move--) {
int path = ((newNum >> move) & 1);
cur.nexts[path] = cur.nexts[path] == null ? new Node() : cur.nexts[path];
cur = cur.nexts[path];
}
}
// 该结构之前收集了一票数字,并且建好了前缀树
// num和 谁 ^ 最大的结果(把结果返回)
public int maxXor(int num) {
Node cur = head;
int ans = 0;
for (int move = 31; move >= 0; move--) {
// 取出num中第move位的状态path只有两种值0就1整数
int path = (num >> move) & 1;
// 期待遇到的东西
int best = move == 31 ? path : (path ^ 1);
// 实际遇到的东西
best = cur.nexts[best] != null ? best : (best ^ 1);
// (path ^ best) 当前位位异或完的结果
ans |= (path ^ best) << move;
cur = cur.nexts[best];
}
return ans;
}
}
// O(N)
public static int maxXorSubarray2(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
int max = Integer.MIN_VALUE;
// 0~i整体异或和
int xor = 0;
NumTrie numTrie = new NumTrie();
numTrie.add(0);
for (int i = 0; i < arr.length; i++) {
xor ^= arr[i]; // 0 ~ i
max = Math.max(max, numTrie.maxXor(xor));
numTrie.add(xor);
}
return max;
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// for test
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 30;
int maxValue = 50;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr = generateRandomArray(maxSize, maxValue);
int comp = maxXorSubarray1(arr);
int res = maxXorSubarray2(arr);
if (res != comp) {
succeed = false;
printArray(arr);
System.out.println(res);
System.out.println(comp);
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
}
}