|
43 | 43 |
|
44 | 44 | <!-- 这里可写通用的实现逻辑 -->
|
45 | 45 |
|
| 46 | +**方法一:两次二分查找** |
| 47 | + |
| 48 | +中位数实际上是排序后第 $target = \left \lceil \frac{m\times n}{2} \right \rceil $ 个数。 |
| 49 | + |
| 50 | +我们二分枚举矩阵的元素 $x$,统计网格中大于该元素的个数 $cnt$,如果 $cnt \ge target$,说明中位数在 $x$ 的左侧(包含 $x$),否则在右侧。 |
| 51 | + |
| 52 | +时间复杂度 $O(m\times \log n \times log M)$,其中 $M$ 为矩阵中的最大值。 |
| 53 | + |
46 | 54 | <!-- tabs:start -->
|
47 | 55 |
|
48 | 56 | ### **Python3**
|
49 | 57 |
|
50 | 58 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
51 | 59 |
|
52 | 60 | ```python
|
53 |
| - |
| 61 | +class Solution: |
| 62 | + def matrixMedian(self, grid: List[List[int]]) -> int: |
| 63 | + def count(x): |
| 64 | + return sum(bisect_right(row, x) for row in grid) |
| 65 | + |
| 66 | + m, n = len(grid), len(grid[0]) |
| 67 | + target = (m * n + 1) >> 1 |
| 68 | + return bisect_left(range(10**6 + 1), target, key=count) |
54 | 69 | ```
|
55 | 70 |
|
56 | 71 | ### **Java**
|
57 | 72 |
|
58 | 73 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
59 | 74 |
|
60 | 75 | ```java
|
| 76 | +class Solution { |
| 77 | + private int[][] grid; |
| 78 | + |
| 79 | + public int matrixMedian(int[][] grid) { |
| 80 | + this.grid = grid; |
| 81 | + int m = grid.length, n = grid[0].length; |
| 82 | + int target = (m * n + 1) >> 1; |
| 83 | + int left = 0, right = 1000010; |
| 84 | + while (left < right) { |
| 85 | + int mid = (left + right) >> 1; |
| 86 | + if (count(mid) >= target) { |
| 87 | + right = mid; |
| 88 | + } else { |
| 89 | + left = mid + 1; |
| 90 | + } |
| 91 | + } |
| 92 | + return left; |
| 93 | + } |
| 94 | + |
| 95 | + private int count(int x) { |
| 96 | + int cnt = 0; |
| 97 | + for (var row : grid) { |
| 98 | + int left = 0, right = row.length; |
| 99 | + while (left < right) { |
| 100 | + int mid = (left + right) >> 1; |
| 101 | + if (row[mid] > x) { |
| 102 | + right = mid; |
| 103 | + } else { |
| 104 | + left = mid + 1; |
| 105 | + } |
| 106 | + } |
| 107 | + cnt += left; |
| 108 | + } |
| 109 | + return cnt; |
| 110 | + } |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +### **C++** |
| 115 | + |
| 116 | +```cpp |
| 117 | +class Solution { |
| 118 | +public: |
| 119 | + int matrixMedian(vector<vector<int>>& grid) { |
| 120 | + int m = grid.size(), n = grid[0].size(); |
| 121 | + int left = 0, right = 1e6 + 1; |
| 122 | + int target = (m * n + 1) >> 1; |
| 123 | + auto count = [&](int x) { |
| 124 | + int cnt = 0; |
| 125 | + for (auto& row : grid) { |
| 126 | + cnt += (upper_bound(row.begin(), row.end(), x) - row.begin()); |
| 127 | + } |
| 128 | + return cnt; |
| 129 | + }; |
| 130 | + while (left < right) { |
| 131 | + int mid = (left + right) >> 1; |
| 132 | + if (count(mid) >= target) { |
| 133 | + right = mid; |
| 134 | + } else { |
| 135 | + left = mid + 1; |
| 136 | + } |
| 137 | + } |
| 138 | + return left; |
| 139 | + } |
| 140 | +}; |
| 141 | +``` |
61 | 142 |
|
| 143 | +### **Go** |
| 144 | +
|
| 145 | +```go |
| 146 | +func matrixMedian(grid [][]int) int { |
| 147 | + m, n := len(grid), len(grid[0]) |
| 148 | +
|
| 149 | + count := func(x int) int { |
| 150 | + cnt := 0 |
| 151 | + for _, row := range grid { |
| 152 | + left, right := 0, n |
| 153 | + for left < right { |
| 154 | + mid := (left + right) >> 1 |
| 155 | + if row[mid] > x { |
| 156 | + right = mid |
| 157 | + } else { |
| 158 | + left = mid + 1 |
| 159 | + } |
| 160 | + } |
| 161 | + cnt += left |
| 162 | + } |
| 163 | + return cnt |
| 164 | + } |
| 165 | + left, right := 0, 1000010 |
| 166 | + target := (m*n + 1) >> 1 |
| 167 | + for left < right { |
| 168 | + mid := (left + right) >> 1 |
| 169 | + if count(mid) >= target { |
| 170 | + right = mid |
| 171 | + } else { |
| 172 | + left = mid + 1 |
| 173 | + } |
| 174 | + } |
| 175 | + return left |
| 176 | +} |
62 | 177 | ```
|
63 | 178 |
|
64 | 179 | ### **TypeScript**
|
|
0 commit comments