Skip to content

Commit 7d4cad5

Browse files
committed
205
1 parent 37c6018 commit 7d4cad5

File tree

3 files changed

+240
-2
lines changed

3 files changed

+240
-2
lines changed

SUMMARY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,5 @@
183183
* [201. Bitwise AND of Numbers Range](leetcode-201-Bitwise-AND-of-Numbers-Range.md)
184184
* [202. Happy Number](leetcode-202-Happy-Number.md)
185185
* [203. Remove Linked List Elements](leetcode-203-Remove-Linked-List-Elements.md)
186-
* [204. Count Primes](leetcode-204-Count-Primes.md)
186+
* [204. Count Primes](leetcode-204-Count-Primes.md)
187+
* [205. Isomorphic Strings](leetcode-205-Isomorphic-Strings.md)

leetcode-201-300.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@
66

77
<a href="leetcode-203-Remove-Linked-List-Elements.html">203. Remove Linked List Elements</a>
88

9-
<a href="leetcode-204-Count-Primes.html">204. Count Primes</a>
9+
<a href="leetcode-204-Count-Primes.html">204. Count Primes</a>
10+
11+
<a href="leetcode-205-Isomorphic-Strings.html">205. Isomorphic Strings</a>

leetcode-205-Isomorphic-Strings.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# 题目描述(简单难度)
2+
3+
![](https://windliang.oss-cn-beijing.aliyuncs.com/205.jpg)
4+
5+
判断两个字符串是否是同构的。
6+
7+
# 解法一
8+
9+
题目描述中已经很详细了,两个字符串同构的含义就是字符串 `s` 可以唯一的映射到 `t` ,同时 `t` 也可以唯一的映射到 `s`
10+
11+
举个具体的例子。
12+
13+
```java
14+
egg 和 add 同构,就意味着下边的映射成立
15+
e -> a
16+
g -> d
17+
也就是将 egg 的 e 换成 a, g 换成 d, 就变成了 add
18+
19+
同时倒过来也成立
20+
a -> e
21+
d -> g
22+
也就是将 add 的 a 换成 e, d 换成 g, 就变成了 egg
23+
24+
foo 和 bar 不同构,原因就是映射不唯一
25+
o -> a
26+
o -> r
27+
其中 o 映射到了两个字母
28+
```
29+
30+
我们可以利用一个 `map` 来处理映射。对于 `s``t` 的映射,我们同时遍历 `s``t` ,假设当前遇到的字母分别是 `c1``c2`
31+
32+
如果 `map[c1]` 不存在,那么就将 `c1` 映射到 `c2` ,即 `map[c1] = c2`
33+
34+
如果 `map[c1]` 存在,那么就判断 `map[c1]` 是否等于 `c2`,也就是验证之前的映射和当前的字母是否相同。
35+
36+
```java
37+
private boolean isIsomorphicHelper(String s, String t) {
38+
int n = s.length();
39+
HashMap<Character, Character> map = new HashMap<>();
40+
for (int i = 0; i < n; i++) {
41+
char c1 = s.charAt(i);
42+
char c2 = s.charAt(i);
43+
if (map.containsKey(c1)) {
44+
if (map.get(c1) != c2) {
45+
return false;
46+
}
47+
} else {
48+
map.put(c1, c2);
49+
}
50+
}
51+
return true;
52+
}
53+
```
54+
55+
对于这道题,我们只需要验证 `s - > t``t -> s` 两个方向即可。如果验证一个方向,是不可以的。
56+
57+
举个例子,`s = ab, t = cc`,如果单看 `s -> t` ,那么 `a -> c, b -> c` 是没有问题的。
58+
59+
必须再验证 `t -> s`,此时,`c -> a, c -> b`,一个字母对应了多个字母,所以不是同构的。
60+
61+
代码的话,只需要调用两次上边的代码即可。
62+
63+
```java
64+
public boolean isIsomorphic(String s, String t) {
65+
return isIsomorphicHelper(s, t) && isIsomorphicHelper(t, s);
66+
67+
}
68+
69+
private boolean isIsomorphicHelper(String s, String t) {
70+
int n = s.length();
71+
HashMap<Character, Character> map = new HashMap<>();
72+
for (int i = 0; i < n; i++) {
73+
char c1 = s.charAt(i);
74+
char c2 = t.charAt(i);
75+
if (map.containsKey(c1)) {
76+
if (map.get(c1) != c2) {
77+
return false;
78+
}
79+
} else {
80+
map.put(c1, c2);
81+
}
82+
}
83+
return true;
84+
}
85+
```
86+
87+
# 解法二
88+
89+
另一种思想,参考 [这里](https://leetcode.com/problems/isomorphic-strings/discuss/57796/My-6-lines-solution)
90+
91+
解法一中,我们判断 `s``t` 是否一一对应,通过对两个方向分别考虑来解决的。
92+
93+
这里的话,我们找一个第三方来解决,即,按照字母出现的顺序,把两个字符串都映射到另一个集合中。
94+
95+
举个现实生活中的例子,一个人说中文,一个人说法语,怎么判断他们说的是一个意思呢?把中文翻译成英语,把法语也翻译成英语,然后看最后的英语是否相同即可。
96+
97+
```java
98+
将第一个出现的字母映射成 1,第二个出现的字母映射成 2
99+
100+
对于 egg
101+
e -> 1
102+
g -> 2
103+
也就是将 egg 的 e 换成 1, g 换成 2, 就变成了 122
104+
105+
对于 add
106+
a -> 1
107+
d -> 2
108+
也就是将 add 的 a 换成 1, d 换成 2, 就变成了 122
109+
110+
egg -> 122, add -> 122
111+
都变成了 122,所以两个字符串异构。
112+
```
113+
114+
代码的话,只需要将两个字符串分别翻译成第三种类型即可。我们可以定义一个变量 `count = 1`,映射给出现的字母,然后进行自增。
115+
116+
```java
117+
public boolean isIsomorphic(String s, String t) {
118+
return isIsomorphicHelper(s).equals(isIsomorphicHelper(t));
119+
}
120+
121+
private String isIsomorphicHelper(String s) {
122+
int[] map = new int[128];
123+
int n = s.length();
124+
StringBuilder sb = new StringBuilder();
125+
int count = 1;
126+
for (int i = 0; i < n; i++) {
127+
char c = s.charAt(i);
128+
//当前字母第一次出现,赋值
129+
if (map[c] == 0) {
130+
map[c] = count;
131+
count++;
132+
}
133+
sb.append(map[c]);
134+
}
135+
return sb.toString();
136+
}
137+
```
138+
139+
为了方便,我们也可以将当前字母直接映射为当前字母的下标加 `1`。因为 `0` 是我们的默认值,所以不能直接赋值为下标,而是「下标加 `1`」。
140+
141+
```java
142+
public boolean isIsomorphic(String s, String t) {
143+
return isIsomorphicHelper(s).equals(isIsomorphicHelper(t));
144+
}
145+
146+
private String isIsomorphicHelper(String s) {
147+
int[] map = new int[128];
148+
int n = s.length();
149+
StringBuilder sb = new StringBuilder();
150+
for (int i = 0; i < n; i++) {
151+
char c = s.charAt(i);
152+
//当前字母第一次出现,赋值
153+
if (map[c] == 0) {
154+
map[c] = i + 1;
155+
}
156+
sb.append(map[c]);
157+
}
158+
return sb.toString();
159+
}
160+
```
161+
162+
上边的 `isIsomorphicHelper` 中我们通过 `map` 记录了当前字母要映射到哪个数字,然后最终返回了整个转换后的字符串。
163+
164+
其实我们不需要将字符串完全转换,我们可以用两个 `map` 分别记录两个字符串每个字母的映射。将所有字母初始都映射到 `0`。记录过程中,如果发现了当前映射不一致,就可以立即返回 `false` 了。
165+
166+
举个例子。
167+
168+
```java
169+
对 abaddee 和 cdbccff
170+
171+
a b a d d e e
172+
c d b c c f f
173+
^
174+
175+
当前
176+
a -> 0
177+
c -> 0
178+
179+
修改映射
180+
a -> 1
181+
c -> 1
182+
183+
a b a d d e e
184+
c d b c c f f
185+
^
186+
187+
当前
188+
b -> 0
189+
d -> 0
190+
191+
修改映射
192+
b -> 2
193+
d -> 2
194+
195+
196+
a b a d d e e
197+
c d b c c f f
198+
^
199+
当前
200+
a -> 1 (之前被修改过)
201+
b -> 0
202+
203+
出现不一致,所以两个字符串不异构
204+
```
205+
206+
代码的话,用两个 `map` 记录映射即可。
207+
208+
```java
209+
public boolean isIsomorphic(String s, String t) {
210+
int n = s.length();
211+
int[] mapS = new int[128];
212+
int[] mapT = new int[128];
213+
for (int i = 0; i < n; i++) {
214+
char c1 = s.charAt(i);
215+
char c2 = t.charAt(i);
216+
//当前的映射值是否相同
217+
if (mapS[c1] != mapT[c2]) {
218+
return false;
219+
} else {
220+
//是否已经修改过,修改过就不需要再处理
221+
if (mapS[c1] == 0) {
222+
mapS[c1] = i + 1;
223+
mapT[c2] = i + 1;
224+
}
225+
}
226+
}
227+
return true;
228+
}
229+
```
230+
231+
#
232+
233+
解法一就是我们比较常规的思路,解法二通过一个第三方的集合,将代码大大简化了,太巧妙了!
234+
235+
题目其实有点像映射的知识,两个字符串为两个集合,然后判断当前映射是否为单射。

0 commit comments

Comments
 (0)