|
48 | 48 |
|
49 | 49 | <!-- 这里可写通用的实现逻辑 -->
|
50 | 50 |
|
| 51 | +**方法一:排序 + 分治** |
| 52 | + |
| 53 | +本题相当于找出平面中两个点,使得它们的曼哈顿距离最小,如果有多个点满足条件,则返回下标字典序最小的点。 |
| 54 | + |
| 55 | +我们先处理重复点的情况,找出每个点对应的下标列表,如果某个点的下标列表长度大于 $1$,那么它的前两个下标可作为候选答案,我们找出最小的下标对即可。 |
| 56 | + |
| 57 | +如果没有重复点,我们将所有点按照 $x$ 坐标排序,然后分治求解。 |
| 58 | + |
| 59 | +对于每个区间 $[l, r]$,我们先求出 $x$ 坐标的中位数 $m$,然后递归求解左右两个区间,分别得到 $d_1, (pi_1, pj_1)$ 和 $d_2, (pi_2, pj_2)$,其中 $d_1$ 和 $d_2$ 分别表示左右两个区间的最小曼哈顿距离,而 $(pi_1, pj_1)$ 和 $(pi_2, pj_2)$ 分别表示左右两个区间的最小曼哈顿距离的两个点的下标。我们取 $d_1$ 和 $d_2$ 中较小的一个,如果 $d_1 = d_2$,则取下标字典序较小的一个,将其作为当前区间的最小曼哈顿距离,同时将对应的两个点的下标作为答案。 |
| 60 | + |
| 61 | +以上考虑的是两个点位于同一侧的情况,如果两个点位于不同侧,那么我们以中间点,即下标为 $m = \lfloor (l + r) / 2 \rfloor$ 的点为标准,划分出一个新的区域,区域的范围为中间点向左右两侧分别扩展 $d_1$ 的范围。然后我们将这些范围内的点按照 $y$ 坐标排序,然后遍历排序后的每个点对,如果两个点的 $y$ 坐标之差大于当前的最小曼哈顿距离,那么后面的点对都不用考虑了,因为它们的 $y$ 坐标之差更大,所以曼哈顿距离更大,不会比当前的最小曼哈顿距离更小。否则,我们更新最小曼哈顿距离,同时更新答案。 |
| 62 | + |
| 63 | +最后,我们返回答案即可。 |
| 64 | + |
| 65 | +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。 |
| 66 | + |
51 | 67 | <!-- tabs:start -->
|
52 | 68 |
|
53 | 69 | ### **Python3**
|
54 | 70 |
|
55 | 71 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
56 | 72 |
|
57 | 73 | ```python
|
58 |
| - |
| 74 | +class Solution: |
| 75 | + def beautifulPair(self, nums1: List[int], nums2: List[int]) -> List[int]: |
| 76 | + def dist(x1: int, y1: int, x2: int, y2: int) -> int: |
| 77 | + return abs(x1 - x2) + abs(y1 - y2) |
| 78 | + |
| 79 | + def dfs(l: int, r: int): |
| 80 | + if l >= r: |
| 81 | + return inf, -1, -1 |
| 82 | + m = (l + r) >> 1 |
| 83 | + x = points[m][0] |
| 84 | + d1, pi1, pj1 = dfs(l, m) |
| 85 | + d2, pi2, pj2 = dfs(m + 1, r) |
| 86 | + if d1 > d2 or (d1 == d2 and (pi1 > pi2 or (pi1 == pi2 and pj1 > pj2))): |
| 87 | + d1, pi1, pj1 = d2, pi2, pj2 |
| 88 | + t = [p for p in points[l: r + 1] if abs(p[0] - x) <= d1] |
| 89 | + t.sort(key=lambda x: x[1]) |
| 90 | + for i in range(len(t)): |
| 91 | + for j in range(i + 1, len(t)): |
| 92 | + if t[j][1] - t[i][1] > d1: |
| 93 | + break |
| 94 | + pi, pj = sorted([t[i][2], t[j][2]]) |
| 95 | + d = dist(t[i][0], t[i][1], t[j][0], t[j][1]) |
| 96 | + if d < d1 or (d == d1 and (pi < pi1 or (pi == pi1 and pj < pj1))): |
| 97 | + d1, pi1, pj1 = d, pi, pj |
| 98 | + return d1, pi1, pj1 |
| 99 | + |
| 100 | + pl = defaultdict(list) |
| 101 | + for i, (x, y) in enumerate(zip(nums1, nums2)): |
| 102 | + pl[(x, y)].append(i) |
| 103 | + points = [] |
| 104 | + for i, (x, y) in enumerate(zip(nums1, nums2)): |
| 105 | + if len(pl[(x, y)]) > 1: |
| 106 | + return [i, pl[(x, y)][1]] |
| 107 | + points.append((x, y, i)) |
| 108 | + points.sort() |
| 109 | + _, pi, pj = dfs(0, len(points) - 1) |
| 110 | + return [pi, pj] |
59 | 111 | ```
|
60 | 112 |
|
61 | 113 | ### **Java**
|
62 | 114 |
|
63 | 115 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
64 | 116 |
|
65 | 117 | ```java
|
66 |
| - |
| 118 | +class Solution { |
| 119 | + private List<int[]> points = new ArrayList<>(); |
| 120 | + |
| 121 | + public int[] beautifulPair(int[] nums1, int[] nums2) { |
| 122 | + int n = nums1.length; |
| 123 | + Map<Long, List<Integer>> pl = new HashMap<>(); |
| 124 | + for (int i = 0; i < n; ++i) { |
| 125 | + long z = f(nums1[i], nums2[i]); |
| 126 | + pl.computeIfAbsent(z, k -> new ArrayList<>()).add(i); |
| 127 | + } |
| 128 | + for (int i = 0; i < n; ++i) { |
| 129 | + long z = f(nums1[i], nums2[i]); |
| 130 | + if (pl.get(z).size() > 1) { |
| 131 | + return new int[]{i, pl.get(z).get(1)}; |
| 132 | + } |
| 133 | + points.add(new int[]{nums1[i], nums2[i], i}); |
| 134 | + } |
| 135 | + points.sort((a, b) -> a[0] - b[0]); |
| 136 | + int[] ans = dfs(0, points.size() - 1); |
| 137 | + return new int[]{ans[1], ans[2]}; |
| 138 | + } |
| 139 | + |
| 140 | + private long f(int x, int y) { |
| 141 | + return x * 100000L + y; |
| 142 | + } |
| 143 | + |
| 144 | + private int dist(int x1, int y1, int x2, int y2) { |
| 145 | + return Math.abs(x1 - x2) + Math.abs(y1 - y2); |
| 146 | + } |
| 147 | + |
| 148 | + private int[] dfs(int l, int r) { |
| 149 | + if (l >= r) { |
| 150 | + return new int[]{1 << 30, -1, -1}; |
| 151 | + } |
| 152 | + int m = (l + r) >> 1; |
| 153 | + int x = points.get(m)[0]; |
| 154 | + int[] t1 = dfs(l, m); |
| 155 | + int[] t2 = dfs(m + 1, r); |
| 156 | + if (t1[0] > t2[0] || (t1[0] == t2[0] && (t1[1] > t2[1] || (t1[1] == t2[1] && t1[2] > t2[2])))) { |
| 157 | + t1 = t2; |
| 158 | + } |
| 159 | + List<int[]> t = new ArrayList<>(); |
| 160 | + for (int i = l; i <= r; ++i) { |
| 161 | + if (Math.abs(points.get(i)[0] - x) <= t1[0]) { |
| 162 | + t.add(points.get(i)); |
| 163 | + } |
| 164 | + } |
| 165 | + t.sort((a, b) -> a[1] - b[1]); |
| 166 | + for (int i = 0; i < t.size(); ++i) { |
| 167 | + for (int j = i + 1; j < t.size(); ++j) { |
| 168 | + if (t.get(j)[1] - t.get(i)[1] > t1[0]) { |
| 169 | + break; |
| 170 | + } |
| 171 | + int pi = Math.min(t.get(i)[2], t.get(j)[2]); |
| 172 | + int pj = Math.max(t.get(i)[2], t.get(j)[2]); |
| 173 | + int d = dist(t.get(i)[0], t.get(i)[1], t.get(j)[0], t.get(j)[1]); |
| 174 | + if (d < t1[0] || (d == t1[0] && (pi < t1[1] || (pi == t1[1] && pj < t1[2])))) { |
| 175 | + t1 = new int[]{d, pi, pj}; |
| 176 | + } |
| 177 | + } |
| 178 | + } |
| 179 | + return t1; |
| 180 | + } |
| 181 | +} |
67 | 182 | ```
|
68 | 183 |
|
69 | 184 | ### **C++**
|
70 | 185 |
|
71 | 186 | ```cpp
|
72 |
| - |
| 187 | +class Solution { |
| 188 | +public: |
| 189 | + vector<int> beautifulPair(vector<int>& nums1, vector<int>& nums2) { |
| 190 | + int n = nums1.size(); |
| 191 | + unordered_map<long long, vector<int>> pl; |
| 192 | + for (int i = 0; i < n; ++i) { |
| 193 | + pl[f(nums1[i], nums2[i])].push_back(i); |
| 194 | + } |
| 195 | + vector<tuple<int, int, int>> points; |
| 196 | + for (int i = 0; i < n; ++i) { |
| 197 | + long long z = f(nums1[i], nums2[i]); |
| 198 | + if (pl[z].size() > 1) { |
| 199 | + return {i, pl[z][1]}; |
| 200 | + } |
| 201 | + points.emplace_back(nums1[i], nums2[i], i); |
| 202 | + } |
| 203 | + |
| 204 | + function<tuple<int, int, int>(int, int)> dfs = [&](int l, int r) -> tuple<int, int, int> { |
| 205 | + if (l >= r) { |
| 206 | + return {1 << 30, -1, -1}; |
| 207 | + } |
| 208 | + int m = (l + r) >> 1; |
| 209 | + int x = get<0>(points[m]); |
| 210 | + auto t1 = dfs(l, m); |
| 211 | + auto t2 = dfs(m + 1, r); |
| 212 | + if (get<0>(t1) > get<0>(t2) || (get<0>(t1) == get<0>(t2) && (get<1>(t1) > get<1>(t2) || (get<1>(t1) == get<1>(t2) && get<2>(t1) > get<2>(t2))))) { |
| 213 | + swap(t1, t2); |
| 214 | + } |
| 215 | + vector<tuple<int, int, int>> t; |
| 216 | + for (int i = l; i <= r; ++i) { |
| 217 | + if (abs(get<0>(points[i]) - x) <= get<0>(t1)) { |
| 218 | + t.emplace_back(points[i]); |
| 219 | + } |
| 220 | + } |
| 221 | + sort(t.begin(), t.end(), [](const tuple<int, int, int>& a, const tuple<int, int, int>& b) { |
| 222 | + return get<1>(a) < get<1>(b); |
| 223 | + }); |
| 224 | + for (int i = 0; i < t.size(); ++i) { |
| 225 | + for (int j = i + 1; j < t.size(); ++j) { |
| 226 | + if (get<1>(t[j]) - get<1>(t[i]) > get<0>(t1)) { |
| 227 | + break; |
| 228 | + } |
| 229 | + int pi = min(get<2>(t[i]), get<2>(t[j])); |
| 230 | + int pj = max(get<2>(t[i]), get<2>(t[j])); |
| 231 | + int d = dist(get<0>(t[i]), get<1>(t[i]), get<0>(t[j]), get<1>(t[j])); |
| 232 | + if (d < get<0>(t1) || (d == get<0>(t1) && (pi < get<1>(t1) || (pi == get<1>(t1) && pj < get<2>(t1))))) { |
| 233 | + t1 = {d, pi, pj}; |
| 234 | + } |
| 235 | + } |
| 236 | + } |
| 237 | + return t1; |
| 238 | + }; |
| 239 | + |
| 240 | + sort(points.begin(), points.end()); |
| 241 | + auto [_, pi, pj] = dfs(0, points.size() - 1); |
| 242 | + return {pi, pj}; |
| 243 | + } |
| 244 | + |
| 245 | + long long f(int x, int y) { |
| 246 | + return x * 100000LL + y; |
| 247 | + } |
| 248 | + |
| 249 | + int dist(int x1, int y1, int x2, int y2) { |
| 250 | + return abs(x1 - x2) + abs(y1 - y2); |
| 251 | + } |
| 252 | +}; |
73 | 253 | ```
|
74 | 254 |
|
75 | 255 | ### **Go**
|
76 | 256 |
|
77 | 257 | ```go
|
| 258 | +func beautifulPair(nums1 []int, nums2 []int) []int { |
| 259 | + n := len(nums1) |
| 260 | + pl := map[[2]int][]int{} |
| 261 | + for i := 0; i < n; i++ { |
| 262 | + k := [2]int{nums1[i], nums2[i]} |
| 263 | + pl[k] = append(pl[k], i) |
| 264 | + } |
| 265 | + points := [][3]int{} |
| 266 | + for i := 0; i < n; i++ { |
| 267 | + k := [2]int{nums2[i], nums1[i]} |
| 268 | + if len(pl[k]) > 1 { |
| 269 | + return []int{pl[k][0], pl[k][1]} |
| 270 | + } |
| 271 | + points = append(points, [3]int{nums1[i], nums2[i], i}) |
| 272 | + } |
| 273 | + sort.Slice(points, func(i, j int) bool { return points[i][0] < points[j][0] }) |
| 274 | + |
| 275 | + var dfs func(l, r int) [3]int |
| 276 | + dfs = func(l, r int) [3]int { |
| 277 | + if l >= r { |
| 278 | + return [3]int{1 << 30, -1, -1} |
| 279 | + } |
| 280 | + m := (l + r) >> 1 |
| 281 | + x := points[m][0] |
| 282 | + t1 := dfs(l, m) |
| 283 | + t2 := dfs(m+1, r) |
| 284 | + if t1[0] > t2[0] || (t1[0] == t2[0] && (t1[1] > t2[1] || (t1[1] == t2[1] && t1[2] > t2[2]))) { |
| 285 | + t1 = t2 |
| 286 | + } |
| 287 | + t := [][3]int{} |
| 288 | + for i := l; i <= r; i++ { |
| 289 | + if abs(points[i][0]-x) <= t1[0] { |
| 290 | + t = append(t, points[i]) |
| 291 | + } |
| 292 | + } |
| 293 | + sort.Slice(t, func(i, j int) bool { return t[i][1] < t[j][1] }) |
| 294 | + for i := 0; i < len(t); i++ { |
| 295 | + for j := i + 1; j < len(t); j++ { |
| 296 | + if t[j][1]-t[i][1] > t1[0] { |
| 297 | + break |
| 298 | + } |
| 299 | + pi := min(t[i][2], t[j][2]) |
| 300 | + pj := max(t[i][2], t[j][2]) |
| 301 | + d := dist(t[i][0], t[i][1], t[j][0], t[j][1]) |
| 302 | + if d < t1[0] || (d == t1[0] && (pi < t1[1] || (pi == t1[1] && pj < t1[2]))) { |
| 303 | + t1 = [3]int{d, pi, pj} |
| 304 | + } |
| 305 | + } |
| 306 | + } |
| 307 | + return t1 |
| 308 | + } |
| 309 | + ans := dfs(0, n-1) |
| 310 | + return []int{ans[1], ans[2]} |
| 311 | +} |
| 312 | + |
| 313 | +func dist(x1, y1, x2, y2 int) int { |
| 314 | + return abs(x1-x2) + abs(y1-y2) |
| 315 | +} |
| 316 | + |
| 317 | +func min(a, b int) int { |
| 318 | + if a < b { |
| 319 | + return a |
| 320 | + } |
| 321 | + return b |
| 322 | +} |
| 323 | + |
| 324 | +func max(a, b int) int { |
| 325 | + if a > b { |
| 326 | + return a |
| 327 | + } |
| 328 | + return b |
| 329 | +} |
| 330 | + |
| 331 | +func abs(x int) int { |
| 332 | + if x < 0 { |
| 333 | + return -x |
| 334 | + } |
| 335 | + return x |
| 336 | +} |
| 337 | +``` |
78 | 338 |
|
| 339 | +### **TypeScript** |
| 340 | + |
| 341 | +```ts |
| 342 | +function beautifulPair(nums1: number[], nums2: number[]): number[] { |
| 343 | + const pl: Map<number, number[]> = new Map(); |
| 344 | + const n = nums1.length; |
| 345 | + for (let i = 0; i < n; ++i) { |
| 346 | + const z = f(nums1[i], nums2[i]); |
| 347 | + if (!pl.has(z)) { |
| 348 | + pl.set(z, []); |
| 349 | + } |
| 350 | + pl.get(z)!.push(i); |
| 351 | + } |
| 352 | + const points: number[][] = []; |
| 353 | + for (let i = 0; i < n; ++i) { |
| 354 | + const z = f(nums1[i], nums2[i]); |
| 355 | + if (pl.get(z)!.length > 1) { |
| 356 | + return [i, pl.get(z)![1]]; |
| 357 | + } |
| 358 | + points.push([nums1[i], nums2[i], i]); |
| 359 | + } |
| 360 | + points.sort((a, b) => a[0] - b[0]); |
| 361 | + |
| 362 | + const dfs = (l: number, r: number): number[] => { |
| 363 | + if (l >= r) { |
| 364 | + return [1 << 30, -1, -1]; |
| 365 | + } |
| 366 | + const m = (l + r) >> 1; |
| 367 | + const x = points[m][0]; |
| 368 | + let t1 = dfs(l, m); |
| 369 | + let t2 = dfs(m + 1, r); |
| 370 | + if ( |
| 371 | + t1[0] > t2[0] || |
| 372 | + (t1[0] == t2[0] && |
| 373 | + (t1[1] > t2[1] || (t1[1] == t2[1] && t1[2] > t2[2]))) |
| 374 | + ) { |
| 375 | + t1 = t2; |
| 376 | + } |
| 377 | + const t: number[][] = []; |
| 378 | + for (let i = l; i <= r; ++i) { |
| 379 | + if (Math.abs(points[i][0] - x) <= t1[0]) { |
| 380 | + t.push(points[i]); |
| 381 | + } |
| 382 | + } |
| 383 | + t.sort((a, b) => a[1] - b[1]); |
| 384 | + for (let i = 0; i < t.length; ++i) { |
| 385 | + for (let j = i + 1; j < t.length; ++j) { |
| 386 | + if (t[j][1] - t[i][1] > t1[0]) { |
| 387 | + break; |
| 388 | + } |
| 389 | + const pi = Math.min(t[i][2], t[j][2]); |
| 390 | + const pj = Math.max(t[i][2], t[j][2]); |
| 391 | + const d = dist(t[i][0], t[i][1], t[j][0], t[j][1]); |
| 392 | + if ( |
| 393 | + d < t1[0] || |
| 394 | + (d == t1[0] && (pi < t1[1] || (pi == t1[1] && pj < t1[2]))) |
| 395 | + ) { |
| 396 | + t1 = [d, pi, pj]; |
| 397 | + } |
| 398 | + } |
| 399 | + } |
| 400 | + return t1; |
| 401 | + }; |
| 402 | + return dfs(0, n - 1).slice(1); |
| 403 | +} |
| 404 | + |
| 405 | +function dist(x1: number, y1: number, x2: number, y2: number): number { |
| 406 | + return Math.abs(x1 - x2) + Math.abs(y1 - y2); |
| 407 | +} |
| 408 | + |
| 409 | +function f(x: number, y: number): number { |
| 410 | + return x * 100000 + y; |
| 411 | +} |
79 | 412 | ```
|
80 | 413 |
|
81 | 414 | ### **...**
|
|
0 commit comments