https://leetcode.com/problems/reverse-pairs/?tab=Description
找出满足i < j && nums[i] > 2 * nums[j]的所有对数
树状数组:
public class Solution {
public int reversePairs(int[] nums) {
int[] copy = Arrays.copyOf(nums, nums.length);
int[] bit = new int[nums.length + 1];
Arrays.sort(copy);
int res = 0;
for (int num : nums) {
res += search(bit, index(copy, 2L * num + 1));
insert(bit, index(copy, num));
}
return res;
}
// 找比当前值大的,要往后找
private int search(int[] bit, int i) {
int sum = 0;
while (i < bit.length) {
sum += bit[i];
i += (i & -i);
}
return sum;
}
// 更新所有小于等于位置i的值所在的bit
private void insert(int[] bit, int i) {
while (i > 0) {
bit[i]++;
i -= (i & -i);
}
}
private int index(int[] nums, long val) {
int i = 0;
int j = nums.length - 1;
while (i <= j) {
int mid = i + (j - i) / 2;
if (nums[mid] >= val) {
j = mid - 1;
} else {
i = mid + 1;
}
}
// 返回bit内的index,要加一
return i + 1;
}
}
BST,在[0, 1, 2, 3.....]大数据量时会超时,主要看思路
public class Solution {
public int reversePairs(int[] nums) {
int cnt = 0;
TreeNode root = null;
for (int num : nums) {
cnt += search(root, 2L * num + 1);
root = insert(num, root);
}
return cnt;
}
private TreeNode insert(int val, TreeNode root) {
if (root == null) {
return new TreeNode(val);
} else if (val == root.val) {
root.cnt++;
} else if (root.val > val) {
root.left = insert(val, root.left);
} else {
root.cnt++;
root.right = insert(val, root.right);
}
return root;
}
private int search(TreeNode root, long val) {
if (root == null) {
return 0;
} else if (root.val == val) {
return root.cnt;
} else if (root.val > val) {
return root.cnt + search(root.left, val);
} else {
return search(root.right, val);
}
}
}
class TreeNode {
int val;
int cnt;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
this.cnt = 1;
}
}
归并排序,合并过程中从左右两个子数组中找到满足条件的对数,因为i < j始终满足,只要找nums[i] > 2 * nums[j]即可
public class Solution {
public int reversePairs(int[] nums) {
return reversePairs(nums, 0, nums.length - 1);
}
private int reversePairs(int[] nums, int beg, int end) {
if (beg >= end) {
return 0;
}
int l = beg;
int m = beg + (end - beg) / 2;
int r = m + 1;
int p = m + 1;
int[] merge = new int[end - beg + 1];
int k = 0;
int res = reversePairs(nums, beg, m) + reversePairs(nums, m + 1, end);
while (l <= m) {
while (p <= end && nums[l] > 2L * nums[p]) {
p++;
}
res += p - (m + 1);
while (r <= end && nums[l] >= nums[r]) {
merge[k++] = nums[r++];
}
merge[k++] = nums[l++];
}
while (r <= end) {
merge[k++] = nums[r++];
}
System.arraycopy(merge, 0, nums, beg, merge.length);
return res;
}
}