|
35 | 35 |
|
36 | 36 | <!-- 这里可写通用的实现逻辑 -->
|
37 | 37 |
|
38 |
| -归并排序实现逆序对统计。 |
| 38 | +**方法一:归并排序** |
| 39 | + |
| 40 | +**方法二:树状数组** |
| 41 | + |
| 42 | +树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作: |
| 43 | + |
| 44 | +1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta; |
| 45 | +1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。 |
| 46 | + |
| 47 | +这两个操作的时间复杂度均为 `O(log n)`。 |
| 48 | + |
| 49 | +树状数组最基本的功能就是求比某点 x 小的点的个数(这里的比较是抽象的概念,可以是数的大小、坐标的大小、质量的大小等等)。 |
| 50 | + |
| 51 | +比如给定数组 `a[5] = {2, 5, 3, 4, 1}`,求 `b[i] = 位置 i 左边小于等于 a[i] 的数的个数`。对于此例,`b[5] = {0, 1, 1, 2, 0}`。 |
| 52 | + |
| 53 | +解决方案是直接遍历数组,每个位置先求出 `query(a[i])`,然后再修改树状数组 `update(a[i], 1)` 即可。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。 |
39 | 54 |
|
40 | 55 | <!-- tabs:start -->
|
41 | 56 |
|
42 | 57 | ### **Python3**
|
43 | 58 |
|
44 | 59 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
45 | 60 |
|
| 61 | +归并排序: |
| 62 | + |
46 | 63 | ```python
|
47 | 64 | class Solution:
|
48 | 65 | def reversePairs(self, nums: List[int]) -> int:
|
@@ -81,10 +98,53 @@ class Solution:
|
81 | 98 | return merge_sort(nums, 0, len(nums) - 1)
|
82 | 99 | ```
|
83 | 100 |
|
| 101 | +树状数组: |
| 102 | + |
| 103 | +```python |
| 104 | +class BinaryIndexedTree: |
| 105 | + def __init__(self, n): |
| 106 | + self.n = n |
| 107 | + self.c = [0] * (n + 1) |
| 108 | + |
| 109 | + @staticmethod |
| 110 | + def lowbit(x): |
| 111 | + return x & -x |
| 112 | + |
| 113 | + def update(self, x, delta): |
| 114 | + while x <= self.n: |
| 115 | + self.c[x] += delta |
| 116 | + x += BinaryIndexedTree.lowbit(x) |
| 117 | + |
| 118 | + def query(self, x): |
| 119 | + s = 0 |
| 120 | + while x > 0: |
| 121 | + s += self.c[x] |
| 122 | + x -= BinaryIndexedTree.lowbit(x) |
| 123 | + return s |
| 124 | + |
| 125 | + |
| 126 | +class Solution: |
| 127 | + def reversePairs(self, nums: List[int]) -> int: |
| 128 | + s = set() |
| 129 | + for num in nums: |
| 130 | + s.add(num) |
| 131 | + s.add(num * 2) |
| 132 | + alls = sorted(s) |
| 133 | + m = {v: i for i, v in enumerate(alls, 1)} |
| 134 | + ans = 0 |
| 135 | + tree = BinaryIndexedTree(len(m)) |
| 136 | + for num in nums[::-1]: |
| 137 | + ans += tree.query(m[num] - 1) |
| 138 | + tree.update(m[num * 2], 1) |
| 139 | + return ans |
| 140 | +``` |
| 141 | + |
84 | 142 | ### **Java**
|
85 | 143 |
|
86 | 144 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
87 | 145 |
|
| 146 | +归并排序: |
| 147 | + |
88 | 148 | ```java
|
89 | 149 | class Solution {
|
90 | 150 | private static int[] tmp = new int[50010];
|
@@ -131,8 +191,67 @@ class Solution {
|
131 | 191 | }
|
132 | 192 | ```
|
133 | 193 |
|
| 194 | +树状数组: |
| 195 | + |
| 196 | +```java |
| 197 | +class Solution { |
| 198 | + public int reversePairs(int[] nums) { |
| 199 | + TreeSet<Long> ts = new TreeSet<>(); |
| 200 | + for (int num : nums) { |
| 201 | + ts.add((long) num); |
| 202 | + ts.add((long) num * 2); |
| 203 | + } |
| 204 | + Map<Long, Integer> m = new HashMap<>(); |
| 205 | + int idx = 0; |
| 206 | + for (long num : ts) { |
| 207 | + m.put(num, ++idx); |
| 208 | + } |
| 209 | + BinaryIndexedTree tree = new BinaryIndexedTree(m.size()); |
| 210 | + int ans = 0; |
| 211 | + for (int i = nums.length - 1; i >= 0; --i) { |
| 212 | + int x = m.get((long) nums[i]); |
| 213 | + ans += tree.query(x - 1); |
| 214 | + tree.update(m.get((long) nums[i] * 2), 1); |
| 215 | + } |
| 216 | + return ans; |
| 217 | + } |
| 218 | +} |
| 219 | + |
| 220 | +class BinaryIndexedTree { |
| 221 | + private int n; |
| 222 | + private int[] c; |
| 223 | + |
| 224 | + public BinaryIndexedTree(int n) { |
| 225 | + this.n = n; |
| 226 | + c = new int[n + 1]; |
| 227 | + } |
| 228 | + |
| 229 | + public void update(int x, int delta) { |
| 230 | + while (x <= n) { |
| 231 | + c[x] += delta; |
| 232 | + x += lowbit(x); |
| 233 | + } |
| 234 | + } |
| 235 | + |
| 236 | + public int query(int x) { |
| 237 | + int s = 0; |
| 238 | + while (x > 0) { |
| 239 | + s += c[x]; |
| 240 | + x -= lowbit(x); |
| 241 | + } |
| 242 | + return s; |
| 243 | + } |
| 244 | + |
| 245 | + public static int lowbit(int x) { |
| 246 | + return x & -x; |
| 247 | + } |
| 248 | +} |
| 249 | +``` |
| 250 | + |
134 | 251 | ### **C++**
|
135 | 252 |
|
| 253 | +归并排序: |
| 254 | + |
136 | 255 | ```cpp
|
137 | 256 | class Solution {
|
138 | 257 | public:
|
@@ -175,8 +294,67 @@ private:
|
175 | 294 | };
|
176 | 295 | ```
|
177 | 296 |
|
| 297 | +树状数组: |
| 298 | +
|
| 299 | +```cpp |
| 300 | +class BinaryIndexedTree { |
| 301 | +public: |
| 302 | + int n; |
| 303 | + vector<int> c; |
| 304 | +
|
| 305 | + BinaryIndexedTree(int _n): n(_n), c(_n + 1){} |
| 306 | +
|
| 307 | + void update(int x, int delta) { |
| 308 | + while (x <= n) |
| 309 | + { |
| 310 | + c[x] += delta; |
| 311 | + x += lowbit(x); |
| 312 | + } |
| 313 | + } |
| 314 | +
|
| 315 | + int query(int x) { |
| 316 | + int s = 0; |
| 317 | + while (x > 0) |
| 318 | + { |
| 319 | + s += c[x]; |
| 320 | + x -= lowbit(x); |
| 321 | + } |
| 322 | + return s; |
| 323 | + } |
| 324 | +
|
| 325 | + int lowbit(int x) { |
| 326 | + return x & -x; |
| 327 | + } |
| 328 | +}; |
| 329 | +
|
| 330 | +class Solution { |
| 331 | +public: |
| 332 | + int reversePairs(vector<int>& nums) { |
| 333 | + set<long long> s; |
| 334 | + for (int num : nums) |
| 335 | + { |
| 336 | + s.insert(num); |
| 337 | + s.insert(num * 2ll); |
| 338 | + } |
| 339 | + unordered_map<long long, int> m; |
| 340 | + int idx = 0; |
| 341 | + for (long long num : s) m[num] = ++idx; |
| 342 | + BinaryIndexedTree* tree = new BinaryIndexedTree(m.size()); |
| 343 | + int ans = 0; |
| 344 | + for (int i = nums.size() - 1; i >= 0; --i) |
| 345 | + { |
| 346 | + ans += tree->query(m[nums[i]] - 1); |
| 347 | + tree->update(m[nums[i] * 2ll], 1); |
| 348 | + } |
| 349 | + return ans; |
| 350 | + } |
| 351 | +}; |
| 352 | +``` |
| 353 | + |
178 | 354 | ### **Go**
|
179 | 355 |
|
| 356 | +归并排序: |
| 357 | + |
180 | 358 | ```go
|
181 | 359 | func reversePairs(nums []int) int {
|
182 | 360 | return mergeSort(nums, 0, len(nums)-1)
|
@@ -223,6 +401,64 @@ func mergeSort(nums []int, left, right int) int {
|
223 | 401 | }
|
224 | 402 | ```
|
225 | 403 |
|
| 404 | +树状数组: |
| 405 | + |
| 406 | +```go |
| 407 | +type BinaryIndexedTree struct { |
| 408 | + n int |
| 409 | + c []int |
| 410 | +} |
| 411 | + |
| 412 | +func newBinaryIndexedTree(n int) *BinaryIndexedTree { |
| 413 | + c := make([]int, n+1) |
| 414 | + return &BinaryIndexedTree{n, c} |
| 415 | +} |
| 416 | + |
| 417 | +func (this *BinaryIndexedTree) lowbit(x int) int { |
| 418 | + return x & -x |
| 419 | +} |
| 420 | + |
| 421 | +func (this *BinaryIndexedTree) update(x, delta int) { |
| 422 | + for x <= this.n { |
| 423 | + this.c[x] += delta |
| 424 | + x += this.lowbit(x) |
| 425 | + } |
| 426 | +} |
| 427 | + |
| 428 | +func (this *BinaryIndexedTree) query(x int) int { |
| 429 | + s := 0 |
| 430 | + for x > 0 { |
| 431 | + s += this.c[x] |
| 432 | + x -= this.lowbit(x) |
| 433 | + } |
| 434 | + return s |
| 435 | +} |
| 436 | + |
| 437 | +func reversePairs(nums []int) int { |
| 438 | + s := make(map[int]bool) |
| 439 | + for _, num := range nums { |
| 440 | + s[num] = true |
| 441 | + s[num*2] = true |
| 442 | + } |
| 443 | + var alls []int |
| 444 | + for num := range s { |
| 445 | + alls = append(alls, num) |
| 446 | + } |
| 447 | + sort.Ints(alls) |
| 448 | + m := make(map[int]int) |
| 449 | + for i, num := range alls { |
| 450 | + m[num] = i + 1 |
| 451 | + } |
| 452 | + tree := newBinaryIndexedTree(len(m)) |
| 453 | + ans := 0 |
| 454 | + for i := len(nums) - 1; i >= 0; i-- { |
| 455 | + ans += tree.query(m[nums[i]] - 1) |
| 456 | + tree.update(m[nums[i]*2], 1) |
| 457 | + } |
| 458 | + return ans |
| 459 | +} |
| 460 | +``` |
| 461 | + |
226 | 462 | ### **...**
|
227 | 463 |
|
228 | 464 | ```
|
|
0 commit comments