Skip to content

Commit 61932c6

Browse files
authored
feat: add solutions to lc problem: No.0288 (#1976)
No.0288.Unique Word Abbreviation
1 parent c9fb852 commit 61932c6

File tree

7 files changed

+218
-127
lines changed

7 files changed

+218
-127
lines changed

solution/0200-0299/0288.Unique Word Abbreviation/README.md

+77-43
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,15 @@ validWordAbbr.isUnique("cake"); // 返回 true,因为 "cake" 已经存在于
6767

6868
<!-- 这里可写通用的实现逻辑 -->
6969

70-
哈希表实现,其中 key 存放单词缩写,value 存放单词缩写所对应的所有单词的集合。
70+
**方法一:哈希表**
71+
72+
根据题目描述,我们定义一个函数 $abbr(s)$,它的功能是计算单词 $s$ 的缩写。如果单词 $s$ 的长度小于 $3$,那么它的缩写就是它本身;否则,它的缩写是它的首字母 + (它的长度 - 2) + 它的尾字母。
73+
74+
接下来,我们定义一个哈希表 $d$,它的键是单词的缩写,值是一个集合,集合中的元素是所有缩写为该键的单词。我们遍历给定的单词字典,对于字典中的每个单词 $s$,我们求出它的缩写 $abbr(s)$,并将 $s$ 添加到 $d[abbr(s)]$ 中。
75+
76+
在判断单词 $word$ 是否满足题目要求时,我们求出它的缩写 $abbr(word)$,如果 $abbr(word)$ 不在哈希表 $d$ 中,那么 $word$ 满足题目要求;否则,我们判断 $d[abbr(word)]$ 中是否只有一个元素,如果 $d[abbr(word)]$ 中只有一个元素且该元素就是 $word$,那么 $word$ 满足题目要求。
77+
78+
时间复杂度方面,初始化哈希表的时间复杂度是 $O(n)$,其中 $n$ 是单词字典的长度;判断单词是否满足题目要求的时间复杂度是 $O(1)$。空间复杂度方面,哈希表的空间复杂度是 $O(n)$。
7179

7280
<!-- tabs:start -->
7381

@@ -78,18 +86,16 @@ validWordAbbr.isUnique("cake"); // 返回 true,因为 "cake" 已经存在于
7886
```python
7987
class ValidWordAbbr:
8088
def __init__(self, dictionary: List[str]):
81-
self.words = defaultdict(set)
82-
for word in dictionary:
83-
abbr = self.word_abbr(word)
84-
self.words[abbr].add(word)
89+
self.d = defaultdict(set)
90+
for s in dictionary:
91+
self.d[self.abbr(s)].add(s)
8592

8693
def isUnique(self, word: str) -> bool:
87-
abbr = self.word_abbr(word)
88-
words = self.words[abbr]
89-
return not words or (len(words) == 1 and word in words)
94+
s = self.abbr(word)
95+
return s not in self.d or all(word == t for t in self.d[s])
9096

91-
def word_abbr(self, s):
92-
return s if len(s) < 3 else f'{s[0]}{len(s) - 2}{s[-1]}'
97+
def abbr(self, s: str) -> str:
98+
return s if len(s) < 3 else s[0] + str(len(s) - 2) + s[-1]
9399

94100

95101
# Your ValidWordAbbr object will be instantiated and called as such:
@@ -103,25 +109,22 @@ class ValidWordAbbr:
103109

104110
```java
105111
class ValidWordAbbr {
106-
private Map<String, Set<String>> words;
112+
private Map<String, Set<String>> d = new HashMap<>();
107113

108114
public ValidWordAbbr(String[] dictionary) {
109-
words = new HashMap<>();
110-
for (String word : dictionary) {
111-
String abbr = abbr(word);
112-
words.computeIfAbsent(abbr, k -> new HashSet<>()).add(word);
115+
for (var s : dictionary) {
116+
d.computeIfAbsent(abbr(s), k -> new HashSet<>()).add(s);
113117
}
114118
}
115119

116120
public boolean isUnique(String word) {
117-
String abbr = abbr(word);
118-
Set<String> vals = words.get(abbr);
119-
return vals == null || (vals.size() == 1 && vals.contains(word));
121+
var ws = d.get(abbr(word));
122+
return ws == null || (ws.size() == 1 && ws.contains(word));
120123
}
121124

122125
private String abbr(String s) {
123126
int n = s.length();
124-
return n < 3 ? s : s.charAt(0) + Integer.toString(n - 2) + s.charAt(n - 1);
127+
return n < 3 ? s : s.substring(0, 1) + (n - 2) + s.substring(n - 1);
125128
}
126129
}
127130

@@ -137,23 +140,21 @@ class ValidWordAbbr {
137140
```cpp
138141
class ValidWordAbbr {
139142
public:
140-
unordered_map<string, unordered_set<string>> words;
141-
142143
ValidWordAbbr(vector<string>& dictionary) {
143-
for (auto word : dictionary) {
144-
auto abbr = wordAbbr(word);
145-
words[abbr].insert(word);
144+
for (auto& s : dictionary) {
145+
d[abbr(s)].insert(s);
146146
}
147147
}
148148

149149
bool isUnique(string word) {
150-
auto abbr = wordAbbr(word);
151-
if (!words.count(abbr)) return true;
152-
auto vals = words[abbr];
153-
return vals.size() == 1 && vals.count(word);
150+
string s = abbr(word);
151+
return !d.count(s) || (d[s].size() == 1 && d[s].count(word));
154152
}
155153

156-
string wordAbbr(string s) {
154+
private:
155+
unordered_map<string, unordered_set<string>> d;
156+
157+
string abbr(string& s) {
157158
int n = s.size();
158159
return n < 3 ? s : s.substr(0, 1) + to_string(n - 2) + s.substr(n - 1, 1);
159160
}
@@ -170,33 +171,32 @@ public:
170171
171172
```go
172173
type ValidWordAbbr struct {
173-
words map[string]map[string]bool
174+
d map[string]map[string]bool
174175
}
175176
176177
func Constructor(dictionary []string) ValidWordAbbr {
177-
words := make(map[string]map[string]bool)
178-
for _, word := range dictionary {
179-
abbr := wordAbbr(word)
180-
if words[abbr] == nil {
181-
words[abbr] = make(map[string]bool)
178+
d := make(map[string]map[string]bool)
179+
for _, s := range dictionary {
180+
abbr := abbr(s)
181+
if _, ok := d[abbr]; !ok {
182+
d[abbr] = make(map[string]bool)
182183
}
183-
words[abbr][word] = true
184+
d[abbr][s] = true
184185
}
185-
return ValidWordAbbr{words}
186+
return ValidWordAbbr{d}
186187
}
187188
188189
func (this *ValidWordAbbr) IsUnique(word string) bool {
189-
abbr := wordAbbr(word)
190-
words := this.words[abbr]
191-
return words == nil || (len(words) == 1 && words[word])
190+
ws := this.d[abbr(word)]
191+
return ws == nil || (len(ws) == 1 && ws[word])
192192
}
193193
194-
func wordAbbr(s string) string {
194+
func abbr(s string) string {
195195
n := len(s)
196-
if n <= 2 {
196+
if n < 3 {
197197
return s
198198
}
199-
return s[0:1] + strconv.Itoa(n-2) + s[n-1:]
199+
return fmt.Sprintf("%c%d%c", s[0], n-2, s[n-1])
200200
}
201201
202202
/**
@@ -206,6 +206,40 @@ func wordAbbr(s string) string {
206206
*/
207207
```
208208

209+
### **TypeScript**
210+
211+
```ts
212+
class ValidWordAbbr {
213+
private d: Map<string, Set<string>> = new Map();
214+
215+
constructor(dictionary: string[]) {
216+
for (const s of dictionary) {
217+
const abbr = this.abbr(s);
218+
if (!this.d.has(abbr)) {
219+
this.d.set(abbr, new Set());
220+
}
221+
this.d.get(abbr)!.add(s);
222+
}
223+
}
224+
225+
isUnique(word: string): boolean {
226+
const ws = this.d.get(this.abbr(word));
227+
return ws === undefined || (ws.size === 1 && ws.has(word));
228+
}
229+
230+
abbr(s: string): string {
231+
const n = s.length;
232+
return n < 3 ? s : s[0] + (n - 2) + s[n - 1];
233+
}
234+
}
235+
236+
/**
237+
* Your ValidWordAbbr object will be instantiated and called as such:
238+
* var obj = new ValidWordAbbr(dictionary)
239+
* var param_1 = obj.isUnique(word)
240+
*/
241+
```
242+
209243
### **...**
210244

211245
```

solution/0200-0299/0288.Unique Word Abbreviation/README_EN.md

+78-42
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,33 @@ validWordAbbr.isUnique(&quot;cake&quot;); // return true, because &quot;cake&quo
5959

6060
## Solutions
6161

62+
**Solution 1: Hash Table**
63+
64+
According to the problem description, we define a function $abbr(s)$, which calculates the abbreviation of the word $s$. If the length of the word $s$ is less than $3$, then its abbreviation is itself; otherwise, its abbreviation is its first letter + (its length - 2) + its last letter.
65+
66+
Next, we define a hash table $d$, where the key is the abbreviation of the word, and the value is a set, the elements of which are all words abbreviated as that key. We traverse the given word dictionary, and for each word $s$ in the dictionary, we calculate its abbreviation $abbr(s)$, and add $s$ to $d[abbr(s)]$.
67+
68+
When judging whether the word $word$ meets the requirements of the problem, we calculate its abbreviation $abbr(word)$. If $abbr(word)$ is not in the hash table $d$, then $word$ meets the requirements of the problem; otherwise, we judge whether there is only one element in $d[abbr(word)]$. If there is only one element in $d[abbr(word)]$ and that element is $word$, then $word$ meets the requirements of the problem.
69+
70+
In terms of time complexity, the time complexity of initializing the hash table is $O(n)$, where $n$ is the length of the word dictionary; the time complexity of judging whether a word meets the requirements of the problem is $O(1)$. In terms of space complexity, the space complexity of the hash table is $O(n)$.
71+
6272
<!-- tabs:start -->
6373

6474
### **Python3**
6575

6676
```python
6777
class ValidWordAbbr:
6878
def __init__(self, dictionary: List[str]):
69-
self.words = defaultdict(set)
70-
for word in dictionary:
71-
abbr = self.word_abbr(word)
72-
self.words[abbr].add(word)
79+
self.d = defaultdict(set)
80+
for s in dictionary:
81+
self.d[self.abbr(s)].add(s)
7382

7483
def isUnique(self, word: str) -> bool:
75-
abbr = self.word_abbr(word)
76-
words = self.words[abbr]
77-
return not words or (len(words) == 1 and word in words)
84+
s = self.abbr(word)
85+
return s not in self.d or all(word == t for t in self.d[s])
7886

79-
def word_abbr(self, s):
80-
return s if len(s) < 3 else f'{s[0]}{len(s) - 2}{s[-1]}'
87+
def abbr(self, s: str) -> str:
88+
return s if len(s) < 3 else s[0] + str(len(s) - 2) + s[-1]
8189

8290

8391
# Your ValidWordAbbr object will be instantiated and called as such:
@@ -89,25 +97,22 @@ class ValidWordAbbr:
8997

9098
```java
9199
class ValidWordAbbr {
92-
private Map<String, Set<String>> words;
100+
private Map<String, Set<String>> d = new HashMap<>();
93101

94102
public ValidWordAbbr(String[] dictionary) {
95-
words = new HashMap<>();
96-
for (String word : dictionary) {
97-
String abbr = abbr(word);
98-
words.computeIfAbsent(abbr, k -> new HashSet<>()).add(word);
103+
for (var s : dictionary) {
104+
d.computeIfAbsent(abbr(s), k -> new HashSet<>()).add(s);
99105
}
100106
}
101107

102108
public boolean isUnique(String word) {
103-
String abbr = abbr(word);
104-
Set<String> vals = words.get(abbr);
105-
return vals == null || (vals.size() == 1 && vals.contains(word));
109+
var ws = d.get(abbr(word));
110+
return ws == null || (ws.size() == 1 && ws.contains(word));
106111
}
107112

108113
private String abbr(String s) {
109114
int n = s.length();
110-
return n < 3 ? s : s.charAt(0) + Integer.toString(n - 2) + s.charAt(n - 1);
115+
return n < 3 ? s : s.substring(0, 1) + (n - 2) + s.substring(n - 1);
111116
}
112117
}
113118

@@ -123,23 +128,21 @@ class ValidWordAbbr {
123128
```cpp
124129
class ValidWordAbbr {
125130
public:
126-
unordered_map<string, unordered_set<string>> words;
127-
128131
ValidWordAbbr(vector<string>& dictionary) {
129-
for (auto word : dictionary) {
130-
auto abbr = wordAbbr(word);
131-
words[abbr].insert(word);
132+
for (auto& s : dictionary) {
133+
d[abbr(s)].insert(s);
132134
}
133135
}
134136

135137
bool isUnique(string word) {
136-
auto abbr = wordAbbr(word);
137-
if (!words.count(abbr)) return true;
138-
auto vals = words[abbr];
139-
return vals.size() == 1 && vals.count(word);
138+
string s = abbr(word);
139+
return !d.count(s) || (d[s].size() == 1 && d[s].count(word));
140140
}
141141

142-
string wordAbbr(string s) {
142+
private:
143+
unordered_map<string, unordered_set<string>> d;
144+
145+
string abbr(string& s) {
143146
int n = s.size();
144147
return n < 3 ? s : s.substr(0, 1) + to_string(n - 2) + s.substr(n - 1, 1);
145148
}
@@ -156,33 +159,32 @@ public:
156159
157160
```go
158161
type ValidWordAbbr struct {
159-
words map[string]map[string]bool
162+
d map[string]map[string]bool
160163
}
161164
162165
func Constructor(dictionary []string) ValidWordAbbr {
163-
words := make(map[string]map[string]bool)
164-
for _, word := range dictionary {
165-
abbr := wordAbbr(word)
166-
if words[abbr] == nil {
167-
words[abbr] = make(map[string]bool)
166+
d := make(map[string]map[string]bool)
167+
for _, s := range dictionary {
168+
abbr := abbr(s)
169+
if _, ok := d[abbr]; !ok {
170+
d[abbr] = make(map[string]bool)
168171
}
169-
words[abbr][word] = true
172+
d[abbr][s] = true
170173
}
171-
return ValidWordAbbr{words}
174+
return ValidWordAbbr{d}
172175
}
173176
174177
func (this *ValidWordAbbr) IsUnique(word string) bool {
175-
abbr := wordAbbr(word)
176-
words := this.words[abbr]
177-
return words == nil || (len(words) == 1 && words[word])
178+
ws := this.d[abbr(word)]
179+
return ws == nil || (len(ws) == 1 && ws[word])
178180
}
179181
180-
func wordAbbr(s string) string {
182+
func abbr(s string) string {
181183
n := len(s)
182-
if n <= 2 {
184+
if n < 3 {
183185
return s
184186
}
185-
return s[0:1] + strconv.Itoa(n-2) + s[n-1:]
187+
return fmt.Sprintf("%c%d%c", s[0], n-2, s[n-1])
186188
}
187189
188190
/**
@@ -192,6 +194,40 @@ func wordAbbr(s string) string {
192194
*/
193195
```
194196

197+
### **TypeScript**
198+
199+
```ts
200+
class ValidWordAbbr {
201+
private d: Map<string, Set<string>> = new Map();
202+
203+
constructor(dictionary: string[]) {
204+
for (const s of dictionary) {
205+
const abbr = this.abbr(s);
206+
if (!this.d.has(abbr)) {
207+
this.d.set(abbr, new Set());
208+
}
209+
this.d.get(abbr)!.add(s);
210+
}
211+
}
212+
213+
isUnique(word: string): boolean {
214+
const ws = this.d.get(this.abbr(word));
215+
return ws === undefined || (ws.size === 1 && ws.has(word));
216+
}
217+
218+
abbr(s: string): string {
219+
const n = s.length;
220+
return n < 3 ? s : s[0] + (n - 2) + s[n - 1];
221+
}
222+
}
223+
224+
/**
225+
* Your ValidWordAbbr object will be instantiated and called as such:
226+
* var obj = new ValidWordAbbr(dictionary)
227+
* var param_1 = obj.isUnique(word)
228+
*/
229+
```
230+
195231
### **...**
196232

197233
```

0 commit comments

Comments
 (0)