20
20
21
21
## 解法
22
22
23
- ### 方法一
23
+ ### 方法一:一次遍历
24
+
25
+ 我们用两个指针 $i$ 和 $j$ 分别记录两个单词 $\textit{word1}$ 和 $\textit{word2}$ 最近出现的位置,初始时 $i = \infty$, $j = -\infty$。
26
+
27
+ 接下来我们遍历整个文本文件,对于每个单词 $w$,如果 $w$ 等于 $\textit{word1}$,我们更新 $i = k$,其中 $k$ 是当前单词的下标;如果 $w$ 等于 $\textit{word2}$,我们更新 $j = k$。然后我们更新答案 $ans = \min(ans, |i - j|)$。
28
+
29
+ 遍历结束后,我们返回答案 $ans$。
30
+
31
+ 时间复杂度 $O(n)$,其中 $n$ 是文本文件中的单词数。空间复杂度 $O(1)$。
24
32
25
33
<!-- tabs:start -->
26
34
27
35
``` python
28
36
class Solution :
29
37
def findClosest (self , words : List[str ], word1 : str , word2 : str ) -> int :
30
- i, j, ans = 1e5 , - 1e5 , 1e5
31
- for k, word in enumerate (words):
32
- if word == word1:
38
+ i, j = inf, - inf
39
+ ans = inf
40
+ for k, w in enumerate (words):
41
+ if w == word1:
33
42
i = k
34
- elif word == word2:
43
+ elif w == word2:
35
44
j = k
36
45
ans = min (ans, abs (i - j))
37
46
return ans
@@ -40,12 +49,12 @@ class Solution:
40
49
``` java
41
50
class Solution {
42
51
public int findClosest (String [] words , String word1 , String word2 ) {
43
- int i = 100000 , j = - 100000 , ans = 100000 ;
52
+ final int inf = 1 << 29 ;
53
+ int i = inf, j = - inf, ans = inf;
44
54
for (int k = 0 ; k < words. length; ++ k) {
45
- String word = words[k];
46
- if (word. equals(word1)) {
55
+ if (words[k]. equals(word1)) {
47
56
i = k;
48
- } else if (word . equals(word2)) {
57
+ } else if (words[k] . equals(word2)) {
49
58
j = k;
50
59
}
51
60
ans = Math . min(ans, Math . abs(i - j));
@@ -59,13 +68,15 @@ class Solution {
59
68
class Solution {
60
69
public:
61
70
int findClosest(vector<string >& words, string word1, string word2) {
62
- int i = 1e5, j = -1e5, ans = 1e5;
71
+ const int inf = 1 << 29;
72
+ int i = inf, j = -inf;
73
+ int ans = inf;
63
74
for (int k = 0; k < words.size(); ++k) {
64
- string word = words[ k] ;
65
- if (word == word1)
75
+ if (words[ k] == word1) {
66
76
i = k;
67
- else if (word == word2)
77
+ } else if (words [ k ] == word2) {
68
78
j = k;
79
+ }
69
80
ans = min(ans, abs(i - j));
70
81
}
71
82
return ans;
@@ -75,70 +86,70 @@ public:
75
86
76
87
```go
77
88
func findClosest(words []string, word1 string, word2 string) int {
78
- i, j, ans := 100000, -100000, 100000
79
- for k, word := range words {
80
- if word == word1 {
89
+ const inf int = 1 << 29
90
+ i, j, ans := inf, -inf, inf
91
+ for k, w := range words {
92
+ if w == word1 {
81
93
i = k
82
- } else if word == word2 {
94
+ } else if w == word2 {
83
95
j = k
84
96
}
85
- ans = min(ans, abs (i-j))
97
+ ans = min(ans, max (i-j, j-i ))
86
98
}
87
99
return ans
88
100
}
89
-
90
- func abs(x int) int {
91
- if x < 0 {
92
- return -x
93
- }
94
- return x
95
- }
96
101
```
97
102
98
103
``` ts
99
104
function findClosest(words : string [], word1 : string , word2 : string ): number {
100
- let index1 = 100000 ;
101
- let index2 = - 100000 ;
102
- let res = 100000 ;
103
- const n = words .length ;
104
- for (let i = 0 ; i < n ; i ++ ) {
105
- const word = words [i ];
106
- if (word === word1 ) {
107
- index1 = i ;
108
- } else if (word === word2 ) {
109
- index2 = i ;
105
+ let [i, j, ans] = [Infinity , - Infinity , Infinity ];
106
+ for (let k = 0 ; k < words .length ; ++ k ) {
107
+ if (words [k ] === word1 ) {
108
+ i = k ;
109
+ } else if (words [k ] === word2 ) {
110
+ j = k ;
110
111
}
111
- res = Math .min (res , Math .abs (index1 - index2 ));
112
+ ans = Math .min (ans , Math .abs (i - j ));
112
113
}
113
- return res ;
114
+ return ans ;
114
115
}
115
116
```
116
117
117
118
``` rust
118
119
impl Solution {
119
120
pub fn find_closest (words : Vec <String >, word1 : String , word2 : String ) -> i32 {
120
- let mut res = i32 :: MAX ;
121
- let mut index1 = - 1 ;
122
- let mut index2 = - 1 ;
123
- for (i , word ) in words . iter (). enumerate () {
124
- let i = i as i32 ;
125
- if word . eq (& word1 ) {
126
- index1 = i ;
127
- } else if word . eq (& word2 ) {
128
- index2 = i ;
121
+ let mut ans = i32 :: MAX ;
122
+ let mut i = - 1 ;
123
+ let mut j = - 1 ;
124
+ for (k , w ) in words . iter (). enumerate () {
125
+ let k = k as i32 ;
126
+ if w . eq (& word1 ) {
127
+ i = k ;
128
+ } else if w . eq (& word2 ) {
129
+ j = k ;
129
130
}
130
- if index1 != - 1 && index2 != - 1 {
131
- res = res . min ((index1 - index2 ). abs ());
131
+ if i != - 1 && j != - 1 {
132
+ ans = ans . min ((i - j ). abs ());
132
133
}
133
134
}
134
- res
135
+ ans
135
136
}
136
137
}
137
138
```
138
139
139
140
<!-- tabs: end -->
140
141
141
- ### 方法二
142
+ ### 方法二:哈希表 + 双指针
143
+
144
+ 我们可以用哈希表 $d$ 记录每个单词出现的位置,然后对于每一对 $\textit{word1}$ 和 $\textit{word2}$,我们可以通过双指针的方法找到它们的最短距离。
145
+
146
+ 我们遍历整个文本文件,对于每个单词 $w$,我们将 $w$ 的下标加入到 $d[ w] $ 中。
147
+
148
+ 接下来我们找到 $\textit{word1}$ 和 $\textit{word2}$ 在文本文件中出现的位置,分别用 $idx1$ 和 $idx2$ 表示。然后我们用两个指针 $i$ 和 $j$ 分别指向 $idx1$ 和 $idx2$,初始时 $i = 0$, $j = 0$。
149
+
150
+ 接下来我们遍历 $idx1$ 和 $idx2$,每次我们更新答案 $ans = \min(ans, |idx1[ i] - idx2[ j] |)$,然后我们将 $i$ 和 $j$ 中较小的那个指针向后移动一位。
151
+
152
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是文本文件中的单词数。
142
153
143
154
<!-- tabs: start -->
144
155
@@ -148,7 +159,7 @@ class Solution:
148
159
d = defaultdict(list )
149
160
for i, w in enumerate (words):
150
161
d[w].append(i)
151
- ans = 1e5
162
+ ans = inf
152
163
idx1, idx2 = d[word1], d[word2]
153
164
i, j, m, n = 0 , 0 , len (idx1), len (idx2)
154
165
while i < m and j < n:
@@ -169,7 +180,7 @@ class Solution {
169
180
}
170
181
List<Integer > idx1 = d. get(word1), idx2 = d. get(word2);
171
182
int i = 0 , j = 0 , m = idx1. size(), n = idx2. size();
172
- int ans = 100000 ;
183
+ int ans = 1 << 29 ;
173
184
while (i < m && j < n) {
174
185
int t = Math . abs(idx1. get(i) - idx2. get(j));
175
186
ans = Math . min(ans, t);
@@ -189,17 +200,20 @@ class Solution {
189
200
public:
190
201
int findClosest(vector<string >& words, string word1, string word2) {
191
202
unordered_map<string, vector<int >> d;
192
- for (int i = 0; i < words.size(); ++i) d[ words[ i]] .push_back(i);
203
+ for (int i = 0; i < words.size(); ++i) {
204
+ d[ words[ i]] .push_back(i);
205
+ }
193
206
vector<int > idx1 = d[ word1] , idx2 = d[ word2] ;
194
207
int i = 0, j = 0, m = idx1.size(), n = idx2.size();
195
208
int ans = 1e5;
196
209
while (i < m && j < n) {
197
210
int t = abs(idx1[ i] - idx2[ j] );
198
211
ans = min(ans, t);
199
- if (idx1[ i] < idx2[ j] )
212
+ if (idx1[ i] < idx2[ j] ) {
200
213
++i;
201
- else
214
+ } else {
202
215
++j;
216
+ }
203
217
}
204
218
return ans;
205
219
}
@@ -214,9 +228,9 @@ func findClosest(words []string, word1 string, word2 string) int {
214
228
}
215
229
idx1, idx2 := d[word1], d[word2]
216
230
i, j, m, n := 0, 0, len(idx1), len(idx2)
217
- ans := 100000
231
+ ans := 1 << 30
218
232
for i < m && j < n {
219
- t := abs (idx1[i] - idx2[j])
233
+ t := max (idx1[i]-idx2[j], idx2[j]-idx1[i ])
220
234
if t < ans {
221
235
ans = t
222
236
}
@@ -228,12 +242,28 @@ func findClosest(words []string, word1 string, word2 string) int {
228
242
}
229
243
return ans
230
244
}
245
+ ```
231
246
232
- func abs(x int) int {
233
- if x < 0 {
234
- return -x
235
- }
236
- return x
247
+ ``` ts
248
+ function findClosest(words : string [], word1 : string , word2 : string ): number {
249
+ const d: Map <string , number []> = new Map ();
250
+ for (let i = 0 ; i < words .length ; ++ i ) {
251
+ if (! d .has (words [i ])) {
252
+ d .set (words [i ], []);
253
+ }
254
+ d .get (words [i ])! .push (i );
255
+ }
256
+ let [i, j] = [0 , 0 ];
257
+ let ans = Infinity ;
258
+ while (i < d .get (word1 )! .length && j < d .get (word2 )! .length ) {
259
+ ans = Math .min (ans , Math .abs (d .get (word1 )! [i ] - d .get (word2 )! [j ]));
260
+ if (d .get (word1 )! [i ] < d .get (word2 )! [j ]) {
261
+ ++ i ;
262
+ } else {
263
+ ++ j ;
264
+ }
265
+ }
266
+ return ans ;
237
267
}
238
268
```
239
269
0 commit comments