Skip to content

Commit 4b4b637

Browse files
committed
feat: add solutions to lc problem: No.2613
No.2613.Beautiful Pairs
1 parent 2da4a4a commit 4b4b637

File tree

8 files changed

+979
-3
lines changed

8 files changed

+979
-3
lines changed

solution/1000-1099/1040.Moving Stones Until Consecutive II/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@
6363

6464
**方法一:排序 + 分类讨论 + 双指针**
6565

66+
我们先对数组 `stones` 进行升序排序,接下来分别考虑最大移动次数 $mx$ 和最小移动次数 $mi$。
67+
68+
对于最大移动次数 $mx$:
69+
70+
由于我们每一次只能选择将端点石子移动到未占用且不是端点石子的位置,如果我们选择 `stones[0]` 作为第一次移动的端点石子,那么从 `stones[0]``stones[1]` 之间的所有未占用的位置都会被跳过,我们可以选择移动到最近的且未占用的位置,接下来每一次都将最左端的石子移动到最近的且未占用的位置,那么最多可以移动的次数为 $stones[n - 1] - stones[1] + 1 - (n - 1)$;同理,如果我们选择 `stones[n - 1]` 作为第一次移动的端点石子,那么最多可以移动的次数为 $stones[n - 2] - stones[0] + 1 - (n - 1)$。取两者的最大值即为最大移动次数 $mx$。
71+
72+
对于最小移动次数 $mi$:
73+
74+
我们用双指针 $i$ 和 $j$ 标识一个窗口的左右端点,若窗口内的位置数 $stones[j] - stones[i] + 1 \gt n$ 时,我们需要缩小窗口,即指针 $i$ 向右移动。如果此时窗口中有连续的 $n-1$ 个石子,即满足 $j - i + 1 = n - 1$ 且 $stones[j] - stones[i] + 1 = n - 1$,那么最少需要移动的次数为 $2$;否则,我们用 $n$ 减去窗口内的石子数,可以得到最少需要移动的次数,即 $n - (j - i + 1)$。取所有情况的最小值即为最小移动次数 $mi$。
75+
6676
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 `stones` 的长度。
6777

6878
<!-- tabs:start -->

solution/2600-2699/2613.Beautiful Pairs/README.md

Lines changed: 336 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,34 +48,367 @@
4848

4949
<!-- 这里可写通用的实现逻辑 -->
5050

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+
5167
<!-- tabs:start -->
5268

5369
### **Python3**
5470

5571
<!-- 这里可写当前语言的特殊实现逻辑 -->
5672

5773
```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]
59111
```
60112

61113
### **Java**
62114

63115
<!-- 这里可写当前语言的特殊实现逻辑 -->
64116

65117
```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+
}
67182
```
68183

69184
### **C++**
70185

71186
```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+
};
73253
```
74254

75255
### **Go**
76256

77257
```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+
```
78338

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+
}
79412
```
80413

81414
### **...**

0 commit comments

Comments
 (0)