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

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