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.
135 lines
2.9 KiB
135 lines
2.9 KiB
package class_2022_02_4_week;
|
|
|
|
import java.util.Arrays;
|
|
|
|
// 返回一个数组中,所有降序三元组的数量
|
|
// 比如 : {5, 3, 4, 2, 1}
|
|
// 所有降序三元组为 :
|
|
// {5, 3, 2}、{5, 3, 1}、{5, 4, 2}、{5, 4, 1}
|
|
// {5, 2, 1}、{3, 2, 1}、{4, 2, 1}
|
|
// 所以返回数量7
|
|
public class Code04_NumberOfDescendingTriples {
|
|
|
|
// 暴力方法
|
|
// 对数器
|
|
public static int num1(int[] arr) {
|
|
if (arr == null || arr.length < 3) {
|
|
return 0;
|
|
}
|
|
return process(arr, 0, new int[3], 0);
|
|
}
|
|
|
|
public static int process(int[] arr, int index, int[] path, int size) {
|
|
if (size == 3) {
|
|
return path[0] > path[1] && path[1] > path[2] ? 1 : 0;
|
|
}
|
|
int ans = 0;
|
|
if (index < arr.length) {
|
|
ans = process(arr, index + 1, path, size);
|
|
path[size] = arr[index];
|
|
ans += process(arr, index + 1, path, size + 1);
|
|
}
|
|
return ans;
|
|
}
|
|
|
|
// 正式方法
|
|
// 时间复杂度O(N * logN)
|
|
// 利用index tree
|
|
public static int num2(int[] arr) {
|
|
if (arr == null || arr.length < 3) {
|
|
return 0;
|
|
}
|
|
int n = arr.length;
|
|
int[] sorted = Arrays.copyOf(arr, n);
|
|
Arrays.sort(sorted);
|
|
int max = Integer.MIN_VALUE;
|
|
for (int i = 0; i < n; i++) {
|
|
arr[i] = rank(sorted, arr[i]);
|
|
max = Math.max(max, arr[i]);
|
|
}
|
|
IndexTree it2 = new IndexTree(max);
|
|
IndexTree it3 = new IndexTree(max);
|
|
int ans = 0;
|
|
for (int i = n - 1; i >= 0; i--) {
|
|
ans += arr[i] == 1 ? 0 : it3.sum(arr[i] - 1);
|
|
it2.add(arr[i], 1);
|
|
it3.add(arr[i], arr[i] == 1 ? 0 : it2.sum(arr[i] - 1));
|
|
}
|
|
return ans;
|
|
}
|
|
|
|
// 返回>=num, 最左位置
|
|
public static int rank(int[] sorted, int num) {
|
|
int l = 0;
|
|
int r = sorted.length - 1;
|
|
int m = 0;
|
|
int ans = 0;
|
|
while (l <= r) {
|
|
m = (l + r) / 2;
|
|
if (sorted[m] >= num) {
|
|
ans = m;
|
|
r = m - 1;
|
|
} else {
|
|
l = m + 1;
|
|
}
|
|
}
|
|
return ans + 1;
|
|
}
|
|
|
|
// 下标从1开始
|
|
public static class IndexTree {
|
|
|
|
private int[] tree;
|
|
private int N;
|
|
|
|
// 0位置弃而不用
|
|
public IndexTree(int size) {
|
|
N = size;
|
|
tree = new int[N + 1];
|
|
}
|
|
|
|
// 1~index 累加和是多少?
|
|
public int sum(int index) {
|
|
int ret = 0;
|
|
while (index > 0) {
|
|
ret += tree[index];
|
|
index -= index & -index;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public void add(int index, int d) {
|
|
while (index <= N) {
|
|
tree[index] += d;
|
|
index += index & -index;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 为了测试
|
|
public static int[] randomArray(int len, int value) {
|
|
int[] arr = new int[len];
|
|
for (int i = 0; i < arr.length; i++) {
|
|
arr[i] = (int) (Math.random() * value) - (int) (Math.random() * value);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
int len = 20;
|
|
int value = 100;
|
|
int testTimes = 10000;
|
|
System.out.println("测试开始");
|
|
for (int i = 0; i < testTimes; i++) {
|
|
int[] arr = randomArray(len, value);
|
|
int ans1 = num1(arr);
|
|
int ans2 = num2(arr);
|
|
if (ans1 != ans2) {
|
|
System.out.println("出错了!");
|
|
}
|
|
}
|
|
System.out.println("测试结束");
|
|
}
|
|
|
|
}
|