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.

103 lines
3.3 KiB

2 years ago
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("测试结束");
}
}