Skip to content

Commit 7a255e2

Browse files
authored
feat: add solutions to lc problem: No.2227 (#4137)
No.2227.Encrypt and Decrypt Strings
1 parent 341a45e commit 7a255e2

File tree

5 files changed

+185
-26
lines changed

5 files changed

+185
-26
lines changed

solution/2200-2299/2227.Encrypt and Decrypt Strings/README.md

+67-9
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ tags:
6161

6262
<strong>解释:</strong>
6363
Encrypter encrypter = new Encrypter([['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]);
64-
encrypter.encrypt("abcd"); // 返回 "eizfeiam"。
64+
encrypter.encrypt("abcd"); // 返回 "eizfeiam"。
6565
&nbsp; // 'a' 映射为 "ei",'b' 映射为 "zf",'c' 映射为 "ei",'d' 映射为 "am"。
66-
encrypter.decrypt("eizfeiam"); // return 2.
67-
// "ei" 可以映射为 'a' 或 'c',"zf" 映射为 'b',"am" 映射为 'd'。
68-
// 因此,解密后可以得到的字符串是 "abad","cbad","abcd" 和 "cbcd"。
66+
encrypter.decrypt("eizfeiam"); // return 2.
67+
// "ei" 可以映射为 'a' 或 'c',"zf" 映射为 'b',"am" 映射为 'd'。
68+
// 因此,解密后可以得到的字符串是 "abad","cbad","abcd" 和 "cbcd"。
6969
// 其中 2 个字符串,"abad" 和 "abcd",在 dictionary 中出现,所以答案是 2 。
7070
</pre>
7171

@@ -95,6 +95,16 @@ encrypter.decrypt("eizfeiam"); // return 2.
9595

9696
### 方法一:哈希表
9797

98+
我们用一个哈希表 $\textit{mp}$ 记录每个字符的加密结果,用另一个哈希表 $\textit{cnt}$ 记录每个加密结果出现的次数。
99+
100+
在构造函数中,我们遍历 $\textit{keys}$ 和 $\textit{values}$,将每个字符和其对应的加密结果存入 $\textit{mp}$ 中。然后遍历 $\textit{dictionary}$,统计每个加密结果出现的次数。时间复杂度 $(n + m)$,其中 $n$ 和 $m$ 分别是 $\textit{keys}$ 和 $\textit{dictionary}$ 的长度。
101+
102+
在加密函数中,我们遍历输入字符串 $\textit{word1}$ 的每个字符,查找其加密结果并拼接起来。如果某个字符没有对应的加密结果,说明无法加密,返回空字符串。时间复杂度 $O(k)$,其中 $k$ 是 $\textit{word1}$ 的长度。
103+
104+
在解密函数中,我们直接返回 $\textit{cnt}$ 中 $\textit{word2}$ 对应的次数。时间复杂度 $O(1)$。
105+
106+
空间复杂度 $O(n + m)$。
107+
98108
<!-- tabs:start -->
99109

100110
#### Python3
@@ -135,8 +145,7 @@ class Encrypter {
135145
mp.put(keys[i], values[i]);
136146
}
137147
for (String w : dictionary) {
138-
w = encrypt(w);
139-
cnt.put(w, cnt.getOrDefault(w, 0) + 1);
148+
cnt.merge(encrypt(w), 1, Integer::sum);
140149
}
141150
}
142151

@@ -173,14 +182,20 @@ public:
173182
unordered_map<char, string> mp;
174183

175184
Encrypter(vector<char>& keys, vector<string>& values, vector<string>& dictionary) {
176-
for (int i = 0; i < keys.size(); ++i) mp[keys[i]] = values[i];
177-
for (auto v : dictionary) cnt[encrypt(v)]++;
185+
for (int i = 0; i < keys.size(); ++i) {
186+
mp[keys[i]] = values[i];
187+
}
188+
for (auto v : dictionary) {
189+
cnt[encrypt(v)]++;
190+
}
178191
}
179192

180193
string encrypt(string word1) {
181194
string res = "";
182195
for (char c : word1) {
183-
if (!mp.count(c)) return "";
196+
if (!mp.count(c)) {
197+
return "";
198+
}
184199
res += mp[c];
185200
}
186201
return res;
@@ -244,6 +259,49 @@ func (this *Encrypter) Decrypt(word2 string) int {
244259
*/
245260
```
246261

262+
#### TypeScript
263+
264+
```ts
265+
class Encrypter {
266+
private mp: Map<string, string> = new Map();
267+
private cnt: Map<string, number> = new Map();
268+
269+
constructor(keys: string[], values: string[], dictionary: string[]) {
270+
for (let i = 0; i < keys.length; i++) {
271+
this.mp.set(keys[i], values[i]);
272+
}
273+
for (const w of dictionary) {
274+
const encrypted = this.encrypt(w);
275+
if (encrypted !== '') {
276+
this.cnt.set(encrypted, (this.cnt.get(encrypted) || 0) + 1);
277+
}
278+
}
279+
}
280+
281+
encrypt(word: string): string {
282+
let res = '';
283+
for (const c of word) {
284+
if (!this.mp.has(c)) {
285+
return '';
286+
}
287+
res += this.mp.get(c);
288+
}
289+
return res;
290+
}
291+
292+
decrypt(word: string): number {
293+
return this.cnt.get(word) || 0;
294+
}
295+
}
296+
297+
/**
298+
* Your Encrypter object will be instantiated and called as such:
299+
* const obj = new Encrypter(keys, values, dictionary);
300+
* const param_1 = obj.encrypt(word1);
301+
* const param_2 = obj.decrypt(word2);
302+
*/
303+
```
304+
247305
<!-- tabs:end -->
248306

249307
<!-- solution:end -->

solution/2200-2299/2227.Encrypt and Decrypt Strings/README_EN.md

+68-10
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ tags:
6060

6161
<strong>Explanation</strong>
6262
Encrypter encrypter = new Encrypter([[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;], [&quot;ei&quot;, &quot;zf&quot;, &quot;ei&quot;, &quot;am&quot;], [&quot;abcd&quot;, &quot;acbd&quot;, &quot;adbc&quot;, &quot;badc&quot;, &quot;dacb&quot;, &quot;cadb&quot;, &quot;cbda&quot;, &quot;abad&quot;]);
63-
encrypter.encrypt(&quot;abcd&quot;); // return &quot;eizfeiam&quot;.
63+
encrypter.encrypt(&quot;abcd&quot;); // return &quot;eizfeiam&quot;.
6464
&nbsp; // &#39;a&#39; maps to &quot;ei&quot;, &#39;b&#39; maps to &quot;zf&quot;, &#39;c&#39; maps to &quot;ei&quot;, and &#39;d&#39; maps to &quot;am&quot;.
65-
encrypter.decrypt(&quot;eizfeiam&quot;); // return 2.
66-
// &quot;ei&quot; can map to &#39;a&#39; or &#39;c&#39;, &quot;zf&quot; maps to &#39;b&#39;, and &quot;am&quot; maps to &#39;d&#39;.
67-
// Thus, the possible strings after decryption are &quot;abad&quot;, &quot;cbad&quot;, &quot;abcd&quot;, and &quot;cbcd&quot;.
65+
encrypter.decrypt(&quot;eizfeiam&quot;); // return 2.
66+
// &quot;ei&quot; can map to &#39;a&#39; or &#39;c&#39;, &quot;zf&quot; maps to &#39;b&#39;, and &quot;am&quot; maps to &#39;d&#39;.
67+
// Thus, the possible strings after decryption are &quot;abad&quot;, &quot;cbad&quot;, &quot;abcd&quot;, and &quot;cbcd&quot;.
6868
// 2 of those strings, &quot;abad&quot; and &quot;abcd&quot;, appear in dictionary, so the answer is 2.
6969
</pre>
7070

@@ -91,7 +91,17 @@ encrypter.decrypt(&quot;eizfeiam&quot;); // return 2.
9191

9292
<!-- solution:start -->
9393

94-
### Solution 1
94+
### Solution 1: Hash Table
95+
96+
We use a hash table $\textit{mp}$ to record the encryption result of each character, and another hash table $\textit{cnt}$ to record the number of occurrences of each encryption result.
97+
98+
In the constructor, we traverse $\textit{keys}$ and $\textit{values}$, storing each character and its corresponding encryption result in $\textit{mp}$. Then, we traverse $\textit{dictionary}$ to count the occurrences of each encryption result. The time complexity is $O(n + m)$, where $n$ and $m$ are the lengths of $\textit{keys}$ and $\textit{dictionary}$, respectively.
99+
100+
In the encryption function, we traverse each character of the input string $\textit{word1}$, look up its encryption result, and concatenate them. If a character does not have a corresponding encryption result, it means encryption is not possible, and we return an empty string. The time complexity is $O(k)$, where $k$ is the length of $\textit{word1}$.
101+
102+
In the decryption function, we directly return the count of $\textit{word2}$ in $\textit{cnt}$. The time complexity is $O(1)$.
103+
104+
The space complexity is $O(n + m)$.
95105

96106
<!-- tabs:start -->
97107

@@ -133,8 +143,7 @@ class Encrypter {
133143
mp.put(keys[i], values[i]);
134144
}
135145
for (String w : dictionary) {
136-
w = encrypt(w);
137-
cnt.put(w, cnt.getOrDefault(w, 0) + 1);
146+
cnt.merge(encrypt(w), 1, Integer::sum);
138147
}
139148
}
140149

@@ -171,14 +180,20 @@ public:
171180
unordered_map<char, string> mp;
172181

173182
Encrypter(vector<char>& keys, vector<string>& values, vector<string>& dictionary) {
174-
for (int i = 0; i < keys.size(); ++i) mp[keys[i]] = values[i];
175-
for (auto v : dictionary) cnt[encrypt(v)]++;
183+
for (int i = 0; i < keys.size(); ++i) {
184+
mp[keys[i]] = values[i];
185+
}
186+
for (auto v : dictionary) {
187+
cnt[encrypt(v)]++;
188+
}
176189
}
177190

178191
string encrypt(string word1) {
179192
string res = "";
180193
for (char c : word1) {
181-
if (!mp.count(c)) return "";
194+
if (!mp.count(c)) {
195+
return "";
196+
}
182197
res += mp[c];
183198
}
184199
return res;
@@ -242,6 +257,49 @@ func (this *Encrypter) Decrypt(word2 string) int {
242257
*/
243258
```
244259

260+
#### TypeScript
261+
262+
```ts
263+
class Encrypter {
264+
private mp: Map<string, string> = new Map();
265+
private cnt: Map<string, number> = new Map();
266+
267+
constructor(keys: string[], values: string[], dictionary: string[]) {
268+
for (let i = 0; i < keys.length; i++) {
269+
this.mp.set(keys[i], values[i]);
270+
}
271+
for (const w of dictionary) {
272+
const encrypted = this.encrypt(w);
273+
if (encrypted !== '') {
274+
this.cnt.set(encrypted, (this.cnt.get(encrypted) || 0) + 1);
275+
}
276+
}
277+
}
278+
279+
encrypt(word: string): string {
280+
let res = '';
281+
for (const c of word) {
282+
if (!this.mp.has(c)) {
283+
return '';
284+
}
285+
res += this.mp.get(c);
286+
}
287+
return res;
288+
}
289+
290+
decrypt(word: string): number {
291+
return this.cnt.get(word) || 0;
292+
}
293+
}
294+
295+
/**
296+
* Your Encrypter object will be instantiated and called as such:
297+
* const obj = new Encrypter(keys, values, dictionary);
298+
* const param_1 = obj.encrypt(word1);
299+
* const param_2 = obj.decrypt(word2);
300+
*/
301+
```
302+
245303
<!-- tabs:end -->
246304

247305
<!-- solution:end -->

solution/2200-2299/2227.Encrypt and Decrypt Strings/Solution.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@ class Encrypter {
44
unordered_map<char, string> mp;
55

66
Encrypter(vector<char>& keys, vector<string>& values, vector<string>& dictionary) {
7-
for (int i = 0; i < keys.size(); ++i) mp[keys[i]] = values[i];
8-
for (auto v : dictionary) cnt[encrypt(v)]++;
7+
for (int i = 0; i < keys.size(); ++i) {
8+
mp[keys[i]] = values[i];
9+
}
10+
for (auto v : dictionary) {
11+
cnt[encrypt(v)]++;
12+
}
913
}
1014

1115
string encrypt(string word1) {
1216
string res = "";
1317
for (char c : word1) {
14-
if (!mp.count(c)) return "";
18+
if (!mp.count(c)) {
19+
return "";
20+
}
1521
res += mp[c];
1622
}
1723
return res;
@@ -27,4 +33,4 @@ class Encrypter {
2733
* Encrypter* obj = new Encrypter(keys, values, dictionary);
2834
* string param_1 = obj->encrypt(word1);
2935
* int param_2 = obj->decrypt(word2);
30-
*/
36+
*/

solution/2200-2299/2227.Encrypt and Decrypt Strings/Solution.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ public Encrypter(char[] keys, String[] values, String[] dictionary) {
77
mp.put(keys[i], values[i]);
88
}
99
for (String w : dictionary) {
10-
w = encrypt(w);
11-
cnt.put(w, cnt.getOrDefault(w, 0) + 1);
10+
cnt.merge(encrypt(w), 1, Integer::sum);
1211
}
1312
}
1413

@@ -33,4 +32,4 @@ public int decrypt(String word2) {
3332
* Encrypter obj = new Encrypter(keys, values, dictionary);
3433
* String param_1 = obj.encrypt(word1);
3534
* int param_2 = obj.decrypt(word2);
36-
*/
35+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
class Encrypter {
2+
private mp: Map<string, string> = new Map();
3+
private cnt: Map<string, number> = new Map();
4+
5+
constructor(keys: string[], values: string[], dictionary: string[]) {
6+
for (let i = 0; i < keys.length; i++) {
7+
this.mp.set(keys[i], values[i]);
8+
}
9+
for (const w of dictionary) {
10+
const encrypted = this.encrypt(w);
11+
if (encrypted !== '') {
12+
this.cnt.set(encrypted, (this.cnt.get(encrypted) || 0) + 1);
13+
}
14+
}
15+
}
16+
17+
encrypt(word: string): string {
18+
let res = '';
19+
for (const c of word) {
20+
if (!this.mp.has(c)) {
21+
return '';
22+
}
23+
res += this.mp.get(c);
24+
}
25+
return res;
26+
}
27+
28+
decrypt(word: string): number {
29+
return this.cnt.get(word) || 0;
30+
}
31+
}
32+
33+
/**
34+
* Your Encrypter object will be instantiated and called as such:
35+
* const obj = new Encrypter(keys, values, dictionary);
36+
* const param_1 = obj.encrypt(word1);
37+
* const param_2 = obj.decrypt(word2);
38+
*/

0 commit comments

Comments
 (0)