|
|
package class07;
|
|
|
|
|
|
// 给定一个正数组成的数组,长度一定大于1,求数组中哪两个数与的结果最大
|
|
|
public class Code01_MaxAndValue {
|
|
|
|
|
|
// O(N^2)的暴力解
|
|
|
public static int maxAndValue1(int[] arr) {
|
|
|
int N = arr.length;
|
|
|
int max = Integer.MIN_VALUE;
|
|
|
for (int i = 0; i < N; i++) {
|
|
|
for (int j = i + 1; j < N; j++) {
|
|
|
max = Math.max(max, arr[i] & arr[j]);
|
|
|
}
|
|
|
}
|
|
|
return max;
|
|
|
}
|
|
|
|
|
|
// O(N)的解
|
|
|
// 因为是正数,所以不用考虑符号位(31位)
|
|
|
// 首先来到30位,假设剩余的数字有N个(整体),看看这一位是1的数,有几个
|
|
|
// 如果有0个、或者1个
|
|
|
// 说明不管怎么在数组中选择,任何两个数&的结果在第30位上都不可能有1了
|
|
|
// 答案在第30位上的状态一定是0,
|
|
|
// 保留剩余的N个数,继续考察第29位,谁也不淘汰(因为谁也不行,干脆接受30位上没有1的事实)
|
|
|
// 如果有2个,
|
|
|
// 说明答案就是这两个数(直接返回答案),因为别的数在第30位都没有1,就这两个数有。
|
|
|
// 如果有>2个,比如K个
|
|
|
// 说明答案一定只用在这K个数中去选择某两个数,因为别的数在第30位都没有1,就这K个数有。
|
|
|
// 答案在第30位上的状态一定是1,
|
|
|
// 只把这K个数作为剩余的数,继续考察第29位,其他数都淘汰掉
|
|
|
// .....
|
|
|
// 现在来到i位,假设剩余的数字有M个,看看这一位是1的数,有几个
|
|
|
// 如果有0个、或者1个
|
|
|
// 说明不管怎么在M个数中选择,任何两个数&的结果在第i位上都不可能有1了
|
|
|
// 答案在第i位上的状态一定是0,
|
|
|
// 保留剩余的M个数,继续考察第i-1位
|
|
|
// 如果有2个,
|
|
|
// 说明答案就是这两个数(直接返回答案),因为别的数在第i位都没有1,就这两个数有。
|
|
|
// 如果有>2个,比如K个
|
|
|
// 说明答案一定只用在这K个数中去选择某两个数,因为别的数在第i位都没有1,就这K个数有。
|
|
|
// 答案在第i位上的状态一定是1,
|
|
|
// 只把这K个数作为剩余的数,继续考察第i-1位,其他数都淘汰掉
|
|
|
public static int maxAndValue2(int[] arr) {
|
|
|
// arr[0...M-1] arr[M....]
|
|
|
int M = arr.length;
|
|
|
int ans = 0;
|
|
|
for (int bit = 30; bit >= 0; bit--) {
|
|
|
// arr[0...M-1] arr[M...]
|
|
|
int i = 0;
|
|
|
int tmp = M;
|
|
|
while (i < M) { // arr[0...M-1]
|
|
|
if ((arr[i] & (1 << bit)) == 0) {
|
|
|
swap(arr, i, --M);
|
|
|
} else {
|
|
|
i++;
|
|
|
}
|
|
|
}
|
|
|
if (M == 2) { // arr[0,1]
|
|
|
return arr[0] & arr[1];
|
|
|
}
|
|
|
if (M < 2) {
|
|
|
M = tmp;
|
|
|
} else { // > 2个数 bit位上有1
|
|
|
ans |= (1 << bit);
|
|
|
}
|
|
|
}
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
public static void swap(int[] arr, int i, int j) {
|
|
|
int tmp = arr[i];
|
|
|
arr[i] = arr[j];
|
|
|
arr[j] = tmp;
|
|
|
}
|
|
|
|
|
|
public static int[] randomArray(int size, int range) {
|
|
|
int[] arr = new int[size];
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
arr[i] = (int) (Math.random() * range) + 1;
|
|
|
}
|
|
|
return arr;
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
int maxSize = 50;
|
|
|
int range = 30;
|
|
|
int testTime = 1000000;
|
|
|
System.out.println("测试开始");
|
|
|
for (int i = 0; i < testTime; i++) {
|
|
|
int size = (int) (Math.random() * maxSize) + 2;
|
|
|
int[] arr = randomArray(size, range);
|
|
|
int ans1 = maxAndValue1(arr);
|
|
|
int ans2 = maxAndValue2(arr);
|
|
|
if (ans1 != ans2) {
|
|
|
System.out.println("Oops!");
|
|
|
}
|
|
|
}
|
|
|
System.out.println("测试结束");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|