Skip to content

[pull] main from doocs:main #406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 67 additions & 9 deletions solution/2200-2299/2227.Encrypt and Decrypt Strings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ tags:

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

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

### 方法一:哈希表

我们用一个哈希表 $\textit{mp}$ 记录每个字符的加密结果,用另一个哈希表 $\textit{cnt}$ 记录每个加密结果出现的次数。

在构造函数中,我们遍历 $\textit{keys}$ 和 $\textit{values}$,将每个字符和其对应的加密结果存入 $\textit{mp}$ 中。然后遍历 $\textit{dictionary}$,统计每个加密结果出现的次数。时间复杂度 $(n + m)$,其中 $n$ 和 $m$ 分别是 $\textit{keys}$ 和 $\textit{dictionary}$ 的长度。

在加密函数中,我们遍历输入字符串 $\textit{word1}$ 的每个字符,查找其加密结果并拼接起来。如果某个字符没有对应的加密结果,说明无法加密,返回空字符串。时间复杂度 $O(k)$,其中 $k$ 是 $\textit{word1}$ 的长度。

在解密函数中,我们直接返回 $\textit{cnt}$ 中 $\textit{word2}$ 对应的次数。时间复杂度 $O(1)$。

空间复杂度 $O(n + m)$。

<!-- tabs:start -->

#### Python3
Expand Down Expand Up @@ -135,8 +145,7 @@ class Encrypter {
mp.put(keys[i], values[i]);
}
for (String w : dictionary) {
w = encrypt(w);
cnt.put(w, cnt.getOrDefault(w, 0) + 1);
cnt.merge(encrypt(w), 1, Integer::sum);
}
}

Expand Down Expand Up @@ -173,14 +182,20 @@ public:
unordered_map<char, string> mp;

Encrypter(vector<char>& keys, vector<string>& values, vector<string>& dictionary) {
for (int i = 0; i < keys.size(); ++i) mp[keys[i]] = values[i];
for (auto v : dictionary) cnt[encrypt(v)]++;
for (int i = 0; i < keys.size(); ++i) {
mp[keys[i]] = values[i];
}
for (auto v : dictionary) {
cnt[encrypt(v)]++;
}
}

string encrypt(string word1) {
string res = "";
for (char c : word1) {
if (!mp.count(c)) return "";
if (!mp.count(c)) {
return "";
}
res += mp[c];
}
return res;
Expand Down Expand Up @@ -244,6 +259,49 @@ func (this *Encrypter) Decrypt(word2 string) int {
*/
```

#### TypeScript

```ts
class Encrypter {
private mp: Map<string, string> = new Map();
private cnt: Map<string, number> = new Map();

constructor(keys: string[], values: string[], dictionary: string[]) {
for (let i = 0; i < keys.length; i++) {
this.mp.set(keys[i], values[i]);
}
for (const w of dictionary) {
const encrypted = this.encrypt(w);
if (encrypted !== '') {
this.cnt.set(encrypted, (this.cnt.get(encrypted) || 0) + 1);
}
}
}

encrypt(word: string): string {
let res = '';
for (const c of word) {
if (!this.mp.has(c)) {
return '';
}
res += this.mp.get(c);
}
return res;
}

decrypt(word: string): number {
return this.cnt.get(word) || 0;
}
}

/**
* Your Encrypter object will be instantiated and called as such:
* const obj = new Encrypter(keys, values, dictionary);
* const param_1 = obj.encrypt(word1);
* const param_2 = obj.decrypt(word2);
*/
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
78 changes: 68 additions & 10 deletions solution/2200-2299/2227.Encrypt and Decrypt Strings/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ tags:

<strong>Explanation</strong>
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;]);
encrypter.encrypt(&quot;abcd&quot;); // return &quot;eizfeiam&quot;.
encrypter.encrypt(&quot;abcd&quot;); // return &quot;eizfeiam&quot;.
&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;.
encrypter.decrypt(&quot;eizfeiam&quot;); // return 2.
// &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;.
// Thus, the possible strings after decryption are &quot;abad&quot;, &quot;cbad&quot;, &quot;abcd&quot;, and &quot;cbcd&quot;.
encrypter.decrypt(&quot;eizfeiam&quot;); // return 2.
// &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;.
// Thus, the possible strings after decryption are &quot;abad&quot;, &quot;cbad&quot;, &quot;abcd&quot;, and &quot;cbcd&quot;.
// 2 of those strings, &quot;abad&quot; and &quot;abcd&quot;, appear in dictionary, so the answer is 2.
</pre>

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

<!-- solution:start -->

### Solution 1
### Solution 1: Hash Table

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.

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.

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}$.

In the decryption function, we directly return the count of $\textit{word2}$ in $\textit{cnt}$. The time complexity is $O(1)$.

The space complexity is $O(n + m)$.

<!-- tabs:start -->

Expand Down Expand Up @@ -133,8 +143,7 @@ class Encrypter {
mp.put(keys[i], values[i]);
}
for (String w : dictionary) {
w = encrypt(w);
cnt.put(w, cnt.getOrDefault(w, 0) + 1);
cnt.merge(encrypt(w), 1, Integer::sum);
}
}

Expand Down Expand Up @@ -171,14 +180,20 @@ public:
unordered_map<char, string> mp;

Encrypter(vector<char>& keys, vector<string>& values, vector<string>& dictionary) {
for (int i = 0; i < keys.size(); ++i) mp[keys[i]] = values[i];
for (auto v : dictionary) cnt[encrypt(v)]++;
for (int i = 0; i < keys.size(); ++i) {
mp[keys[i]] = values[i];
}
for (auto v : dictionary) {
cnt[encrypt(v)]++;
}
}

string encrypt(string word1) {
string res = "";
for (char c : word1) {
if (!mp.count(c)) return "";
if (!mp.count(c)) {
return "";
}
res += mp[c];
}
return res;
Expand Down Expand Up @@ -242,6 +257,49 @@ func (this *Encrypter) Decrypt(word2 string) int {
*/
```

#### TypeScript

```ts
class Encrypter {
private mp: Map<string, string> = new Map();
private cnt: Map<string, number> = new Map();

constructor(keys: string[], values: string[], dictionary: string[]) {
for (let i = 0; i < keys.length; i++) {
this.mp.set(keys[i], values[i]);
}
for (const w of dictionary) {
const encrypted = this.encrypt(w);
if (encrypted !== '') {
this.cnt.set(encrypted, (this.cnt.get(encrypted) || 0) + 1);
}
}
}

encrypt(word: string): string {
let res = '';
for (const c of word) {
if (!this.mp.has(c)) {
return '';
}
res += this.mp.get(c);
}
return res;
}

decrypt(word: string): number {
return this.cnt.get(word) || 0;
}
}

/**
* Your Encrypter object will be instantiated and called as such:
* const obj = new Encrypter(keys, values, dictionary);
* const param_1 = obj.encrypt(word1);
* const param_2 = obj.decrypt(word2);
*/
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
14 changes: 10 additions & 4 deletions solution/2200-2299/2227.Encrypt and Decrypt Strings/Solution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@ class Encrypter {
unordered_map<char, string> mp;

Encrypter(vector<char>& keys, vector<string>& values, vector<string>& dictionary) {
for (int i = 0; i < keys.size(); ++i) mp[keys[i]] = values[i];
for (auto v : dictionary) cnt[encrypt(v)]++;
for (int i = 0; i < keys.size(); ++i) {
mp[keys[i]] = values[i];
}
for (auto v : dictionary) {
cnt[encrypt(v)]++;
}
}

string encrypt(string word1) {
string res = "";
for (char c : word1) {
if (!mp.count(c)) return "";
if (!mp.count(c)) {
return "";
}
res += mp[c];
}
return res;
Expand All @@ -27,4 +33,4 @@ class Encrypter {
* Encrypter* obj = new Encrypter(keys, values, dictionary);
* string param_1 = obj->encrypt(word1);
* int param_2 = obj->decrypt(word2);
*/
*/
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ public Encrypter(char[] keys, String[] values, String[] dictionary) {
mp.put(keys[i], values[i]);
}
for (String w : dictionary) {
w = encrypt(w);
cnt.put(w, cnt.getOrDefault(w, 0) + 1);
cnt.merge(encrypt(w), 1, Integer::sum);
}
}

Expand All @@ -33,4 +32,4 @@ public int decrypt(String word2) {
* Encrypter obj = new Encrypter(keys, values, dictionary);
* String param_1 = obj.encrypt(word1);
* int param_2 = obj.decrypt(word2);
*/
*/
38 changes: 38 additions & 0 deletions solution/2200-2299/2227.Encrypt and Decrypt Strings/Solution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class Encrypter {
private mp: Map<string, string> = new Map();
private cnt: Map<string, number> = new Map();

constructor(keys: string[], values: string[], dictionary: string[]) {
for (let i = 0; i < keys.length; i++) {
this.mp.set(keys[i], values[i]);
}
for (const w of dictionary) {
const encrypted = this.encrypt(w);
if (encrypted !== '') {
this.cnt.set(encrypted, (this.cnt.get(encrypted) || 0) + 1);
}
}
}

encrypt(word: string): string {
let res = '';
for (const c of word) {
if (!this.mp.has(c)) {
return '';
}
res += this.mp.get(c);
}
return res;
}

decrypt(word: string): number {
return this.cnt.get(word) || 0;
}
}

/**
* Your Encrypter object will be instantiated and called as such:
* const obj = new Encrypter(keys, values, dictionary);
* const param_1 = obj.encrypt(word1);
* const param_2 = obj.decrypt(word2);
*/