目录
最近几篇算法,我们都是聊的归并排序,今天再开一篇。再聊两题。
一、大于右侧数的两倍
怕大家忘了归并排序,所以先拿一题练练手。
1、题目描述
求给定数组中,当前数 大于 右侧数的两倍 的个数
2、例子
数组:[6, 7, 3, 2, 1]
当前数大于右侧数的两倍的数有(6,2),(6,1),(7,3),(7,2),(7,1),(3,1)
所有总共有6个。
3、思路
认真看过小和问题和逆序对问题的伙伴都知道,我们在求解时,都是和merge操作放在一起的。但是此题再和merge操作放在一起求解,难度、代码复杂度就很大了。
所以,很简单,我们把 求个数的操作 和 merge操作 分成两个循环单独求,瞬间就豁然开朗了。
4、详细的参考代码
只有merge操作的代码,其他和归并排序的一模一样
private static int merge(int[] arr, int l, int mid, int r) {
int num = 0;
// l...mid, mid+1...r, 目前右组寻找的范围 [mid+1, windowR)
int windowR = mid + 1;
for (int i = l; i <= mid; i++) {
while (windowR <= r && arr[i] > (arr[windowR] << 1)) {
windowR++;
}
// 此时,符合条件的个数为 (windowR - (mid+1))
// 因为此时windowR不满足要求,所以不是(windowR - (mid+1)) +1
num += windowR - mid - 1;
}
int[] help = new int[r - l + 1];
int i = 0;
int pL = l;
int pR = mid + 1;
while (pL <= mid && pR <= r) {
// 谁小拷贝谁(相等的拷贝左组的)
help[i++] =