|
| 1 | +--- |
| 2 | +comments: true |
| 3 | +difficulty: 中等 |
| 4 | +edit_url: https://github.com/doocs/leetcode/edit/main/solution/3800-3899/3809.Best%20Reachable%20Tower/README.md |
| 5 | +--- |
| 6 | + |
| 7 | +<!-- problem:start --> |
| 8 | + |
| 9 | +# [3809. 最好可到达的塔](https://leetcode.cn/problems/best-reachable-tower) |
| 10 | + |
| 11 | +[English Version](/solution/3800-3899/3809.Best%20Reachable%20Tower/README_EN.md) |
| 12 | + |
| 13 | +## 题目描述 |
| 14 | + |
| 15 | +<!-- description:start --> |
| 16 | + |
| 17 | +<p>给你一个二维整数数组 <code>towers</code>,其中 <code>towers[i] = [x<sub>i</sub>, y<sub>i</sub>, q<sub>i</sub>]</code> 表示第 <code>i</code> 座塔的坐标 <code>(x<sub>i</sub>, y<sub>i</sub>)</code> 和质量因子 <code>q<sub>i</sub></code>。</p> |
| 18 | + |
| 19 | +<p>另外给你一个整数数组 <code>center = [cx, cy]</code> 表示你的位置,以及一个整数 <code>radius</code>。</p> |
| 20 | + |
| 21 | +<p>如果一座塔与 <code>center</code> 之间的 <strong>曼哈顿距离</strong><strong>小于或等于</strong> <code>radius</code>,则称该塔是 <strong>可到达的</strong>。</p> |
| 22 | + |
| 23 | +<p>在所有可到达的塔中:</p> |
| 24 | + |
| 25 | +<ul> |
| 26 | + <li>返回质量因子 <strong>最大</strong> 的塔的坐标。</li> |
| 27 | + <li>如果存在并列的塔,返回坐标 <strong>字典序最小</strong> 的塔。如果没有塔是可到达的,返回 <code>[-1, -1]</code>。</li> |
| 28 | +</ul> |
| 29 | +两点 <code>(x<sub>i</sub>, y<sub>i</sub>)</code> 和 <code>(x<sub>j</sub>, y<sub>j</sub>)</code> 之间的 <strong>曼哈顿距离</strong> 为 <code>|x<sub>i</sub> - x<sub>j</sub>| + |y<sub>i</sub> - y<sub>j</sub>|</code>。 |
| 30 | + |
| 31 | +<p>坐标 <code>[x<sub>i</sub>, y<sub>i</sub>]</code> <strong>字典序小于</strong> <code>[x<sub>j</sub>, y<sub>j</sub>]</code> 是指:<code>x<sub>i</sub> < x<sub>j</sub></code>,或者 <code>x<sub>i</sub> == x<sub>j</sub></code> 且 <code>y<sub>i</sub> < y<sub>j</sub></code>。</p> |
| 32 | + |
| 33 | +<p><code>|x|</code> 表示 <code>x</code> 的 <strong>绝对值</strong>。</p> |
| 34 | + |
| 35 | +<p> </p> |
| 36 | + |
| 37 | +<p><strong class="example">示例 1:</strong></p> |
| 38 | + |
| 39 | +<div class="example-block"> |
| 40 | +<p><strong>输入:</strong> <span class="example-io">towers = [[1,2,5], [2,1,7], [3,1,9]], center = [1,1], radius = 2</span></p> |
| 41 | + |
| 42 | +<p><strong>输出:</strong> <span class="example-io">[3,1]</span></p> |
| 43 | + |
| 44 | +<p><strong>解释:</strong></p> |
| 45 | + |
| 46 | +<ul> |
| 47 | + <li>塔 <code>[1, 2, 5]</code>:曼哈顿距离 = <code>|1 - 1| + |2 - 1| = 1</code>,可到达。</li> |
| 48 | + <li>塔 <code>[2, 1, 7]</code>:曼哈顿距离 = <code>|2 - 1| + |1 - 1| = 1</code>,可到达。</li> |
| 49 | + <li>塔 <code>[3, 1, 9]</code>:曼哈顿距离 = <code>|3 - 1| + |1 - 1| = 2</code>,可到达。</li> |
| 50 | +</ul> |
| 51 | + |
| 52 | +<p>所有塔都是可到达的。最大质量因子为 9,对应塔 <code>[3, 1]</code>。</p> |
| 53 | +</div> |
| 54 | + |
| 55 | +<p><strong class="example">示例 2:</strong></p> |
| 56 | + |
| 57 | +<div class="example-block"> |
| 58 | +<p><strong>输入:</strong> <span class="example-io">towers = [[1,3,4], [2,2,4], [4,4,7]], center = [0,0], radius = 5</span></p> |
| 59 | + |
| 60 | +<p><strong>输出:</strong> <span class="example-io">[1,3]</span></p> |
| 61 | + |
| 62 | +<p><strong>解释:</strong></p> |
| 63 | + |
| 64 | +<ul> |
| 65 | + <li>塔 <code>[1, 3, 4]</code>:曼哈顿距离 = <code>|1 - 0| + |3 - 0| = 4</code>,可到达。</li> |
| 66 | + <li>塔 <code>[2, 2, 4]</code>:曼哈顿距离 = <code>|2 - 0| + |2 - 0| = 4</code>,可到达。</li> |
| 67 | + <li>塔 <code>[4, 4, 7]</code>:曼哈顿距离 = <code>|4 - 0| + |4 - 0| = 8</code>,不可到达。</li> |
| 68 | +</ul> |
| 69 | + |
| 70 | +<p>在可到达的塔中,最大质量因子为 4。<code>[1, 3]</code> 和 <code>[2, 2]</code> 的质量因子相同,因此返回字典序较小的坐标 <code>[1, 3]</code>。</p> |
| 71 | +</div> |
| 72 | + |
| 73 | +<p><strong class="example">示例 3:</strong></p> |
| 74 | + |
| 75 | +<div class="example-block"> |
| 76 | +<p><strong>输入:</strong> <span class="example-io">towers = [[5,6,8], [0,3,5]], center = [1,2], radius = 1</span></p> |
| 77 | + |
| 78 | +<p><strong>输出:</strong> <span class="example-io">[-1,-1]</span></p> |
| 79 | + |
| 80 | +<p><strong>解释:</strong></p> |
| 81 | + |
| 82 | +<ul> |
| 83 | + <li>塔 <code>[5, 6, 8]</code>:曼哈顿距离 = <code>|5 - 1| + |6 - 2| = 8</code>,不可到达。</li> |
| 84 | + <li>塔 <code>[0, 3, 5]</code>:曼哈顿距离 = <code>|0 - 1| + |3 - 2| = 2</code>,不可到达。</li> |
| 85 | +</ul> |
| 86 | + |
| 87 | +<p>在给定半径内没有可到达的塔,故返回 <code>[-1, -1]</code>。</p> |
| 88 | +</div> |
| 89 | + |
| 90 | +<p> </p> |
| 91 | + |
| 92 | +<p><strong>提示:</strong></p> |
| 93 | + |
| 94 | +<ul> |
| 95 | + <li><code>1 <= towers.length <= 10<sup>5</sup></code></li> |
| 96 | + <li><code>towers[i] = [x<sub>i</sub>, y<sub>i</sub>, q<sub>i</sub>]</code></li> |
| 97 | + <li><code>center = [cx, cy]</code></li> |
| 98 | + <li><code>0 <= x<sub>i</sub>, y<sub>i</sub>, q<sub>i</sub>, cx, cy <= 10<sup>5</sup></code></li> |
| 99 | + <li><code>0 <= radius <= 10<sup>5</sup></code></li> |
| 100 | +</ul> |
| 101 | + |
| 102 | +<!-- description:end --> |
| 103 | + |
| 104 | +## 解法 |
| 105 | + |
| 106 | +<!-- solution:start --> |
| 107 | + |
| 108 | +### 方法一:一次遍历 |
| 109 | + |
| 110 | +我们定义一个变量 $\textit{idx}$ 来记录当前最佳塔的下标,初始时 $\textit{idx} = -1$。然后我们遍历每一座塔,计算其与 $\textit{center}$ 之间的曼哈顿距离 $\textit{dist}$: |
| 111 | + |
| 112 | +$$ |
| 113 | +\textit{dist} = |x_i - cx| + |y_i - cy| |
| 114 | +$$ |
| 115 | + |
| 116 | +如果 $\textit{dist} > \textit{radius}$,则该塔不可到达,跳过该塔。否则,我们比较当前塔与最佳塔的质量因子 $q$: |
| 117 | + |
| 118 | +- 如果 $\textit{idx} = -1$,说明当前还没有可到达的塔,我们将 $\textit{idx}$ 更新为当前塔的下标。 |
| 119 | +- 如果当前塔的质量因子 $q_i$ 大于最佳塔的质量因子 $q_{\textit{idx}}$,则将 $\textit{idx}$ 更新为当前塔的下标。 |
| 120 | +- 如果当前塔的质量因子 $q_i$ 等于最佳塔的质量因子 $q_{\textit{idx}}$,则比较两座塔的坐标,选择字典序较小的塔。 |
| 121 | + |
| 122 | +遍历结束后,如果 $\textit{idx} = -1$,说明没有可到达的塔,返回 $[-1, -1]$。否则,返回最佳塔的坐标。 |
| 123 | + |
| 124 | +时间复杂度 $O(n)$,其中 $n$ 是塔的数量。空间复杂度 $O(1)$。 |
| 125 | + |
| 126 | +<!-- tabs:start --> |
| 127 | + |
| 128 | +#### Python3 |
| 129 | + |
| 130 | +```python |
| 131 | +class Solution: |
| 132 | + def bestTower( |
| 133 | + self, towers: List[List[int]], center: List[int], radius: int |
| 134 | + ) -> List[int]: |
| 135 | + cx, cy = center |
| 136 | + idx = -1 |
| 137 | + for i, (x, y, q) in enumerate(towers): |
| 138 | + dist = abs(x - cx) + abs(y - cy) |
| 139 | + if dist > radius: |
| 140 | + continue |
| 141 | + if ( |
| 142 | + idx == -1 |
| 143 | + or towers[idx][2] < q |
| 144 | + or (towers[idx][2] == q and towers[i][:2] < towers[idx][:2]) |
| 145 | + ): |
| 146 | + idx = i |
| 147 | + return [-1, -1] if idx == -1 else towers[idx][:2] |
| 148 | +``` |
| 149 | + |
| 150 | +#### Java |
| 151 | + |
| 152 | +```java |
| 153 | +class Solution { |
| 154 | + public int[] bestTower(int[][] towers, int[] center, int radius) { |
| 155 | + int cx = center[0], cy = center[1]; |
| 156 | + int idx = -1; |
| 157 | + for (int i = 0; i < towers.length; i++) { |
| 158 | + int x = towers[i][0], y = towers[i][1], q = towers[i][2]; |
| 159 | + int dist = Math.abs(x - cx) + Math.abs(y - cy); |
| 160 | + if (dist > radius) { |
| 161 | + continue; |
| 162 | + } |
| 163 | + if (idx == -1 || towers[idx][2] < q |
| 164 | + || (towers[idx][2] == q |
| 165 | + && (x < towers[idx][0] || (x == towers[idx][0] && y < towers[idx][1])))) { |
| 166 | + idx = i; |
| 167 | + } |
| 168 | + } |
| 169 | + return idx == -1 ? new int[] {-1, -1} : new int[] {towers[idx][0], towers[idx][1]}; |
| 170 | + } |
| 171 | +} |
| 172 | +``` |
| 173 | + |
| 174 | +#### C++ |
| 175 | + |
| 176 | +```cpp |
| 177 | +class Solution { |
| 178 | +public: |
| 179 | + vector<int> bestTower(vector<vector<int>>& towers, vector<int>& center, int radius) { |
| 180 | + int cx = center[0], cy = center[1]; |
| 181 | + int idx = -1; |
| 182 | + for (int i = 0; i < towers.size(); ++i) { |
| 183 | + int x = towers[i][0], y = towers[i][1], q = towers[i][2]; |
| 184 | + int dist = abs(x - cx) + abs(y - cy); |
| 185 | + if (dist > radius) { |
| 186 | + continue; |
| 187 | + } |
| 188 | + if ( |
| 189 | + idx == -1 |
| 190 | + || towers[idx][2] < q |
| 191 | + || (towers[idx][2] == q && (x < towers[idx][0] || (x == towers[idx][0] && y < towers[idx][1])))) { |
| 192 | + idx = i; |
| 193 | + } |
| 194 | + } |
| 195 | + if (idx == -1) { |
| 196 | + return {-1, -1}; |
| 197 | + } |
| 198 | + return {towers[idx][0], towers[idx][1]}; |
| 199 | + } |
| 200 | +}; |
| 201 | +``` |
| 202 | +
|
| 203 | +#### Go |
| 204 | +
|
| 205 | +```go |
| 206 | +func bestTower(towers [][]int, center []int, radius int) []int { |
| 207 | + cx, cy := center[0], center[1] |
| 208 | + idx := -1 |
| 209 | + for i, a := range towers { |
| 210 | + x, y, q := a[0], a[1], a[2] |
| 211 | + dist := abs(x-cx) + abs(y-cy) |
| 212 | + if dist > radius { |
| 213 | + continue |
| 214 | + } |
| 215 | + if idx == -1 || |
| 216 | + towers[idx][2] < q || |
| 217 | + (towers[idx][2] == q && |
| 218 | + (x < towers[idx][0] || |
| 219 | + (x == towers[idx][0] && y < towers[idx][1]))) { |
| 220 | + idx = i |
| 221 | + } |
| 222 | + } |
| 223 | + if idx == -1 { |
| 224 | + return []int{-1, -1} |
| 225 | + } |
| 226 | + return []int{towers[idx][0], towers[idx][1]} |
| 227 | +} |
| 228 | +
|
| 229 | +func abs(x int) int { |
| 230 | + if x < 0 { |
| 231 | + return -x |
| 232 | + } |
| 233 | + return x |
| 234 | +} |
| 235 | +``` |
| 236 | + |
| 237 | +#### TypeScript |
| 238 | + |
| 239 | +```ts |
| 240 | +function bestTower(towers: number[][], center: number[], radius: number): number[] { |
| 241 | + const [cx, cy] = center; |
| 242 | + let idx = -1; |
| 243 | + for (let i = 0; i < towers.length; i++) { |
| 244 | + const [x, y, q] = towers[i]; |
| 245 | + const dist = Math.abs(x - cx) + Math.abs(y - cy); |
| 246 | + if (dist > radius) { |
| 247 | + continue; |
| 248 | + } |
| 249 | + if ( |
| 250 | + idx === -1 || |
| 251 | + towers[idx][2] < q || |
| 252 | + (towers[idx][2] === q && |
| 253 | + (x < towers[idx][0] || (x === towers[idx][0] && y < towers[idx][1]))) |
| 254 | + ) { |
| 255 | + idx = i; |
| 256 | + } |
| 257 | + } |
| 258 | + return idx === -1 ? [-1, -1] : [towers[idx][0], towers[idx][1]]; |
| 259 | +} |
| 260 | +``` |
| 261 | + |
| 262 | +<!-- tabs:end --> |
| 263 | + |
| 264 | +<!-- solution:end --> |
| 265 | + |
| 266 | +<!-- problem:end --> |
0 commit comments