在一个数组中, 对于每个数num,求有多少个后面的数 * 2 依然<num,求总个数 比如:[3,1,7,0,2] 3的后面有:1,0 1的后面有:0 7的后面有:0,2 0的后面没有 2的后面没有 所以总共有5个
思路
1 归并排序 merge 中 merge 与计算 个数分开写
2 循环L-m 和m+1 到R 对比 如果符合 右边 数 * 2 依然<左边的数 右边的下标++
3 循环L-m 和m+1 到R 对比 如果是 右边 数 * 2 依然>左边的数 累加小于的有几个(windowR-m-1;) 右边边的下标++
package class04;
public class Code04_BiggerThanRightTwice {
public static int biggerTwice(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
return process(arr, 0, arr.length - 1);
}
public static int process(int[] arr, int l, int r) {
if (l == r) {
return 0;
}
// l < r
int mid = l + ((r - l) >> 1);
return process(arr, l, mid) + process(arr, mid + 1, r) + merge(arr, l, mid, r);
}
public static int merge(int[] arr, int L, int m, int r) {
// [L....M] [M+1....R]
int ans = 0;
// 目前囊括进来的数,是从[M+1, windowR)
int windowR = m + 1;
//循环左边L-M
for (int i = L; i <= m; i++) {
//对比右边,如果 左边 > 右边 * 2 就右边再跳一位
while (windowR <= r && arr[i] > (arr[windowR] * 2)) {
windowR++;
}
//算出右边数*2 比当前左边的数小 的数有几个
ans += windowR - m - 1;
}
//归并排序 合并
int[] help = new int[r - L + 1];
int i = 0;
int p1 = L;
int p2 = m + 1;
while (p1 <= m && p2 <= r) {
help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= m) {
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[L + i] = help[i];
}
return ans;
}
// for test
public static int comparator(int[] arr) {
int ans = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > (arr[j] << 1)) {
ans++;
}
}
}
return ans;
}
// 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 + 1) * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// 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 = 100;
int maxValue = 100;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
if (biggerTwice(arr1) != comparator(arr2)) {
System.out.println("Oops!");
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println("测试结束");
}
}