Skip to content

Commit 12f0d6f

Browse files
committed
feat: add solutions to lc problem: No.0290
No.0290.Word Pattern
1 parent 62ebae9 commit 12f0d6f

File tree

8 files changed

+297
-263
lines changed

8 files changed

+297
-263
lines changed

solution/0200-0299/0290.Word Pattern/README.md

+104-107
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,15 @@
4747

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

50-
**朴素解法:**
50+
**方法一:哈希表**
5151

52-
给对应的字符打上印记,使用该字符首次出现的索引位置作为印记值,使用哈希表记录
52+
我们先将字符串 $s$ 按照空格分割成单词数组 $ws$,如果 $pattern$ 和 $ws$ 的长度不相等,直接返回 `false`。否则,我们使用两个哈希表 $d_1$ 和 $d_2$,分别记录 $pattern$ 和 $ws$ 中每个字符和单词的对应关系
5353

54-
而后,将字符串转换为对应的索引数组,如 `pattern = "abbac"`,转换后为 `[0, 1, 1, 0, 4]`。对于字符串 `s` 同理
54+
接下来,我们遍历 $pattern$ 和 $ws$,对于每个字符 $a$ 和单词 $b$,如果 $d_1$ 中存在 $a$ 的映射,且映射的单词不是 $b$,或者 $d_2$ 中存在 $b$ 的映射,且映射的字符不是 $a$,则返回 `false`。否则,我们将 $a$ 和 $b$ 的映射分别加入 $d_1$ 和 $d_2$ 中
5555

56-
> 需注意,`pattern``char``key`;而 `s` 则是以 `' '` 作为分割符,转换为字符串数组之后,以成员 `String``key`
56+
遍历结束后,返回 `true`
5757

58-
对比两个索引数组,在所有成员一一对应的情况下,才能表示两者规律一致。
59-
60-
优化:
61-
62-
转换为索引数组方便理解,但是太浪费。
63-
64-
可以选择再次遍历字符串,以 `key` 取值对比即可。
58+
时间复杂度 $O(m + n)$,空间复杂度 $O(m + n)$。其中 $m$ 和 $n$ 分别是 $pattern$ 和字符串 $s$ 的长度。
6559

6660
<!-- tabs:start -->
6761

@@ -72,18 +66,16 @@
7266
```python
7367
class Solution:
7468
def wordPattern(self, pattern: str, s: str) -> bool:
75-
s = s.split(' ')
76-
n = len(pattern)
77-
if n != len(s):
69+
ws = s.split()
70+
if len(pattern) != len(ws):
7871
return False
79-
c2str, str2c = defaultdict(), defaultdict()
80-
for i in range(n):
81-
k, v = pattern[i], s[i]
82-
if k in c2str and c2str[k] != v:
83-
return False
84-
if v in str2c and str2c[v] != k:
72+
d1 = {}
73+
d2 = {}
74+
for a, b in zip(pattern, ws):
75+
if (a in d1 and d1[a] != b) or (b in d2 and d2[b] != a):
8576
return False
86-
c2str[k], str2c[v] = v, k
77+
d1[a] = b
78+
d2[b] = a
8779
return True
8880
```
8981

@@ -94,99 +86,50 @@ class Solution:
9486
```java
9587
class Solution {
9688
public boolean wordPattern(String pattern, String s) {
97-
String[] ss = s.split(" ");
98-
int n = pattern.length();
99-
if (n != ss.length) {
89+
String[] ws = s.split(" ");
90+
if (pattern.length() != ws.length) {
10091
return false;
10192
}
102-
Map<Character, String> c2str = new HashMap<>();
103-
Map<String, Character> str2c = new HashMap<>();
104-
for (int i = 0; i < n; ++i) {
105-
char k = pattern.charAt(i);
106-
String v = ss[i];
107-
if (c2str.containsKey(k) && !Objects.equals(c2str.get(k), v)) {
93+
Map<Character, String> d1 = new HashMap<>();
94+
Map<String, Character> d2 = new HashMap<>();
95+
for (int i = 0; i < ws.length; ++i) {
96+
char a = pattern.charAt(i);
97+
String b = ws[i];
98+
if (!d1.getOrDefault(a, b).equals(b) || d2.getOrDefault(b, a) != a) {
10899
return false;
109100
}
110-
if (str2c.containsKey(v) && !Objects.equals(str2c.get(v), k)) {
111-
return false;
112-
}
113-
c2str.put(k, v);
114-
str2c.put(v, k);
101+
d1.put(a, b);
102+
d2.put(b, a);
115103
}
116104
return true;
117105
}
118106
}
119107
```
120108

121-
### **TypeScript**
122-
123-
```ts
124-
function wordPattern(pattern: string, s: string): boolean {
125-
let n = pattern.length;
126-
let values = s.split(' ');
127-
if (n != values.length) return false;
128-
let table = new Array(128);
129-
for (let i = 0; i < n; i++) {
130-
let k = pattern.charCodeAt(i),
131-
v = values[i];
132-
if (!table[k]) {
133-
if (table.includes(v)) return false;
134-
table[k] = v;
135-
} else {
136-
if (table[k] != v) return false;
137-
}
138-
}
139-
return true;
140-
}
141-
```
142-
143-
```ts
144-
function wordPattern(pattern: string, s: string): boolean {
145-
const n = pattern.length;
146-
const cs = s.split(' ');
147-
if (n !== cs.length) {
148-
return false;
149-
}
150-
const map1 = new Map<string, number>();
151-
const map2 = new Map<string, number>();
152-
for (let i = 0; i < n; i++) {
153-
const c1 = pattern[i];
154-
const c2 = cs[i];
155-
if (!map1.has(c1)) {
156-
map1.set(c1, i);
157-
}
158-
if (!map2.has(c2)) {
159-
map2.set(c2, i);
160-
}
161-
if (map1.get(c1) !== map2.get(c2)) {
162-
return false;
163-
}
164-
}
165-
return true;
166-
}
167-
```
168-
169109
### **C++**
170110

171111
```cpp
172112
class Solution {
173113
public:
174114
bool wordPattern(string pattern, string s) {
175115
istringstream is(s);
176-
vector<string> ss;
177-
while (is >> s) ss.push_back(s);
178-
int n = pattern.size();
179-
if (n != ss.size()) return false;
180-
181-
unordered_map<char, string> c2str;
182-
unordered_map<string, char> str2c;
183-
for (int i = 0; i < n; ++i) {
184-
char k = pattern[i];
185-
string v = ss[i];
186-
if (c2str.count(k) && c2str[k] != v) return false;
187-
if (str2c.count(v) && str2c[v] != k) return false;
188-
c2str[k] = v;
189-
str2c[v] = k;
116+
vector<string> ws;
117+
while (is >> s) {
118+
ws.push_back(s);
119+
}
120+
if (pattern.size() != ws.size()) {
121+
return false;
122+
}
123+
unordered_map<char, string> d1;
124+
unordered_map<string, char> d2;
125+
for (int i = 0; i < ws.size(); ++i) {
126+
char a = pattern[i];
127+
string b = ws[i];
128+
if ((d1.count(a) && d1[a] != b) || (d2.count(b) && d2[b] != a)) {
129+
return false;
130+
}
131+
d1[a] = b;
132+
d2[b] = a;
190133
}
191134
return true;
192135
}
@@ -197,27 +140,81 @@ public:
197140
198141
```go
199142
func wordPattern(pattern string, s string) bool {
200-
ss := strings.Split(s, " ")
201-
n := len(pattern)
202-
if n != len(ss) {
143+
ws := strings.Split(s, " ")
144+
if len(ws) != len(pattern) {
203145
return false
204146
}
205-
c2str := make(map[byte]string)
206-
str2c := make(map[string]byte)
207-
for i := 0; i < n; i++ {
208-
k, v := pattern[i], ss[i]
209-
if c2str[k] != "" && c2str[k] != v {
147+
d1 := map[rune]string{}
148+
d2 := map[string]rune{}
149+
for i, a := range pattern {
150+
b := ws[i]
151+
if v, ok := d1[a]; ok && v != b {
210152
return false
211153
}
212-
if str2c[v] > 0 && str2c[v] != k {
154+
if v, ok := d2[b]; ok && v != a {
213155
return false
214156
}
215-
c2str[k], str2c[v] = v, k
157+
d1[a] = b
158+
d2[b] = a
216159
}
217160
return true
218161
}
219162
```
220163

164+
### **TypeScript**
165+
166+
```ts
167+
function wordPattern(pattern: string, s: string): boolean {
168+
const ws = s.split(' ');
169+
if (pattern.length !== ws.length) {
170+
return false;
171+
}
172+
const d1 = new Map<string, string>();
173+
const d2 = new Map<string, string>();
174+
for (let i = 0; i < pattern.length; ++i) {
175+
const a = pattern[i];
176+
const b = ws[i];
177+
if (d1.has(a) && d1.get(a) !== b) {
178+
return false;
179+
}
180+
if (d2.has(b) && d2.get(b) !== a) {
181+
return false;
182+
}
183+
d1.set(a, b);
184+
d2.set(b, a);
185+
}
186+
return true;
187+
}
188+
```
189+
190+
### **C#**
191+
192+
```cs
193+
public class Solution {
194+
public bool WordPattern(string pattern, string s) {
195+
var ws = s.Split(' ');
196+
if (pattern.Length != ws.Length) {
197+
return false;
198+
}
199+
var d1 = new Dictionary<char, string>();
200+
var d2 = new Dictionary<string, char>();
201+
for (int i = 0; i < ws.Length; ++i) {
202+
var a = pattern[i];
203+
var b = ws[i];
204+
if (d1.ContainsKey(a) && d1[a] != b) {
205+
return false;
206+
}
207+
if (d2.ContainsKey(b) && d2[b] != a) {
208+
return false;
209+
}
210+
d1[a] = b;
211+
d2[b] = a;
212+
}
213+
return true;
214+
}
215+
}
216+
```
217+
221218
### **Rust**
222219

223220
```rust

0 commit comments

Comments
 (0)