我们可以为两个数组分别维护指针 i,j。对于任意给定的 i 而言,我们不断地向右移动 j,直到 nums}[i] \le 2\cdot \textit{nums}[j]。此时,意味着以 i 为左端点的翻转对数量为 j-m-1。随后,我们再将 i 向右移动一个单位,并用相同的方式计算以 i 为左端点的翻转对数量。不断重复这样的过程,就能够求出所有左右端点分别位于两个子数组的翻转对数目。
classSolution { public: intreversePairsRecursive(vector<int>& nums, int left, int right){ if (left == right) { return0; } else { int mid = (left + right) / 2; int n1 = reversePairsRecursive(nums, left, mid); int n2 = reversePairsRecursive(nums, mid + 1, right); int ret = n1 + n2;
// 首先统计下标对的数量 int i = left; int j = mid + 1; while (i <= mid) { while (j <= right && (longlong)nums[i] > 2 * (longlong)nums[j]) j++; ret += (j - mid - 1); i++; }
// 随后合并两个排序数组 vector<int> sorted(right - left + 1); int p1 = left, p2 = mid + 1; int p = 0; while (p1 <= mid || p2 <= right) { if (p1 > mid) { sorted[p++] = nums[p2++]; } elseif (p2 > right) { sorted[p++] = nums[p1++]; } else { if (nums[p1] < nums[p2]) { sorted[p++] = nums[p1++]; } else { sorted[p++] = nums[p2++]; } } } for (int i = 0; i < sorted.size(); i++) { nums[left + i] = sorted[i]; } return ret; } }
intreversePairsRecursive(int* nums, int left, int right) { if (left == right) { return0; } else { int mid = (left + right) / 2; int n1 = reversePairsRecursive(nums, left, mid); int n2 = reversePairsRecursive(nums, mid + 1, right); int ret = n1 + n2;
// 首先统计下标对的数量 int i = left; int j = mid + 1; while (i <= mid) { while (j <= right && (longlong)nums[i] > 2 * (longlong)nums[j]) j++; ret += (j - mid - 1); i++; }
// 随后合并两个排序数组 int sorted[right - left + 1]; int p1 = left, p2 = mid + 1; int p = 0; while (p1 <= mid || p2 <= right) { if (p1 > mid) { sorted[p++] = nums[p2++]; } elseif (p2 > right) { sorted[p++] = nums[p1++]; } else { if (nums[p1] < nums[p2]) { sorted[p++] = nums[p1++]; } else { sorted[p++] = nums[p2++]; } } } for (int i = 0; i < right - left + 1; i++) { nums[left + i] = sorted[i]; } return ret; } }
intreversePairs(int* nums, int numsSize) { if (numsSize == 0) { return0; } return reversePairsRecursive(nums, 0, numsSize - 1); }
staticconstexprintlowbit(int x){ return x & (-x); }
voidupdate(int x, int d){ while (x <= n) { tree[x] += d; x += lowbit(x); } }
intquery(int x)const{ int ans = 0; while (x) { ans += tree[x]; x -= lowbit(x); } return ans; } };
classSolution { public: intreversePairs(vector<int>& nums){ set<longlong> allNumbers; for (int x : nums) { allNumbers.insert(x); allNumbers.insert((longlong)x * 2); } // 利用哈希表进行离散化 unordered_map<longlong, int> values; int idx = 0; for (longlong x : allNumbers) { values[x] = ++idx; }
int ret = 0; BIT bit(values.size()); for (int i = 0; i < nums.size(); i++) { int left = values[(longlong)nums[i] * 2], right = values.size(); ret += bit.query(right) - bit.query(left); bit.update(values[nums[i]], 1); } return ret; } };
voidupdate(int* tree, int treeSize, int x, int d) { while (x <= treeSize) { tree[x] += d; x += lowbit(x); } }
intquery(int* tree, int x) { int ans = 0; while (x) { ans += tree[x]; x -= lowbit(x); } return ans; }
intcmp(void* _a, void* _b) { longlong a = *((longlong*)_a), b = *((longlong*)_b); return a < b ? -1 : 1; }
intlower_bound(longlong* a, int aSize, longlong target) { int left = 0, right = aSize; while (left < right) { int mid = (left + right) / 2; if (a[mid] < target) { left = mid + 1; } else { right = mid; } } return left; }
intdiscrete(int* nums, int numsSize, int* ret) { longlong rec[numsSize * 2]; for (int i = 0; i < numsSize; i++) { rec[i * 2] = nums[i], rec[i * 2 + 1] = (longlong)nums[i] * 2; } qsort(rec, numsSize * 2, sizeof(longlong), cmp); int retSize = 0; for (int i = 0; i < numsSize * 2; i++) { if (retSize == 0 || rec[retSize - 1] != rec[i]) { rec[retSize++] = rec[i]; } } for (int i = 0; i < numsSize; i++) { ret[i * 2] = lower_bound(rec, retSize, nums[i]) + 1; ret[i * 2 + 1] = lower_bound(rec, retSize, (longlong)nums[i] * 2) + 1; } return retSize; }
intreversePairs(int* nums, int numsSize) { if (numsSize == 0) { return0; }
int values[numsSize * 2]; int valuesSize = discrete(nums, numsSize, values); int ret = 0; int tree[valuesSize + 2]; memset(tree, 0, sizeof(tree)); for (int i = 0; i < numsSize; i++) { int left = values[i * 2 + 1], right = valuesSize + 1; ret += query(tree, right) - query(tree, left); update(tree, valuesSize + 1, values[i * 2], 1); } return ret; }
let ret = 0; const bit = newBIT(values.size); for (let i = 0; i < nums.length; i++) { let left = values.get(nums[i] * 2), right = values.size; ret += bit.query(right) - bit.query(left); bit.update(values.get(nums[i]), 1); } return ret; };