Skip to content

Commit 9d6999d

Browse files
committed
Add solution and test-cases for problem 2227
1 parent f03226b commit 9d6999d

File tree

3 files changed

+142
-29
lines changed

3 files changed

+142
-29
lines changed

leetcode/2201-2300/2227.Encrypt-and-Decrypt-Strings/README.md

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,44 @@
11
# [2227.Encrypt and Decrypt Strings][title]
22

3-
> [!WARNING|style:flat]
4-
> This question is temporarily unanswered if you have good ideas. Welcome to [Create Pull Request PR](https://github.com/kylesliu/awesome-golang-algorithm)
5-
63
## Description
4+
You are given a character array `keys` containing unique characters and a string array `values` containing strings of length 2. You are also given another string array `dictionary` that contains all permitted original strings after decryption. You should implement a data structure that can encrypt or decrypt a **0-indexed** string.
75

8-
**Example 1:**
6+
A string is **encrypted** with the following process:
97

10-
```
11-
Input: a = "11", b = "1"
12-
Output: "100"
13-
```
8+
1. For each character `c` in the string, we find the index `i` satisfying `keys[i] == c` in `keys`.
9+
2. Replace `c` with `values[i]` in the string.
1410

15-
## 题意
16-
> ...
11+
Note that in case a character of the string is **not present** in `keys`, the encryption process cannot be carried out, and an empty string `""` is returned.
1712

18-
## 题解
13+
A string is **decrypted** with the following process:
1914

20-
### 思路1
21-
> ...
22-
Encrypt and Decrypt Strings
23-
```go
24-
```
15+
1. For each substring `s` of length 2 occurring at an even index in the string, we find an `i` such that `values[i] == s`. If there are multiple valid `i`, we choose **any** one of them. This means a string could have multiple possible strings it can decrypt to.
16+
2. Replace `s` with `keys[i]` in the string.
17+
18+
Implement the `Encrypter` class:
2519

20+
- `Encrypter(char[] keys, String[] values, String[] dictionary)` Initializes the `Encrypter` class with `keys`, `values`, and `dictionary`.
21+
- `String encrypt(String word1)` Encrypts `word1` with the encryption process described above and returns the encrypted string.
22+
- `int decrypt(String word2)` Returns the number of possible strings `word2` could decrypt to that also appear in `dictionary`.
23+
24+
**Example 1:**
25+
26+
```
27+
Input
28+
["Encrypter", "encrypt", "decrypt"]
29+
[[['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]], ["abcd"], ["eizfeiam"]]
30+
Output
31+
[null, "eizfeiam", 2]
32+
33+
Explanation
34+
Encrypter encrypter = new Encrypter([['a', 'b', 'c', 'd'], ["ei", "zf", "ei", "am"], ["abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"]);
35+
encrypter.encrypt("abcd"); // return "eizfeiam".
36+
// 'a' maps to "ei", 'b' maps to "zf", 'c' maps to "ei", and 'd' maps to "am".
37+
encrypter.decrypt("eizfeiam"); // return 2.
38+
// "ei" can map to 'a' or 'c', "zf" maps to 'b', and "am" maps to 'd'.
39+
// Thus, the possible strings after decryption are "abad", "cbad", "abcd", and "cbcd".
40+
// 2 of those strings, "abad" and "abcd", appear in dictionary, so the answer is 2.
41+
```
2642

2743
## 结语
2844

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,102 @@
11
package Solution
22

3-
func Solution(x bool) bool {
4-
return x
3+
import (
4+
"strings"
5+
)
6+
7+
type trieNode2227 struct {
8+
child [26]*trieNode2227
9+
end bool
10+
}
11+
12+
func buildTrieNode2227(dic []string) *trieNode2227 {
13+
root := &trieNode2227{
14+
child: [26]*trieNode2227{},
15+
}
16+
for _, word := range dic {
17+
walker := root
18+
for _, b := range []byte(word) {
19+
index := b - 'a'
20+
if walker.child[index] == nil {
21+
walker.child[index] = &trieNode2227{}
22+
}
23+
walker = walker.child[index]
24+
}
25+
walker.end = true
26+
}
27+
return root
28+
}
29+
30+
type Encrypter struct {
31+
tree *trieNode2227
32+
keys []byte
33+
keysMap map[byte]int
34+
values []string
35+
valuesMapper map[string][]int
36+
}
37+
38+
func Constructor(keys []byte, values []string, dictionary []string) Encrypter {
39+
tree := buildTrieNode2227(dictionary)
40+
e := Encrypter{
41+
tree: tree,
42+
keys: keys,
43+
keysMap: make(map[byte]int),
44+
values: values,
45+
valuesMapper: map[string][]int{},
46+
}
47+
for i, b := range keys {
48+
e.keysMap[b] = i
49+
}
50+
for i, str := range values {
51+
if _, ok := e.valuesMapper[str]; !ok {
52+
e.valuesMapper[str] = []int{}
53+
}
54+
e.valuesMapper[str] = append(e.valuesMapper[str], i)
55+
}
56+
57+
return e
58+
}
59+
60+
func (this *Encrypter) Encrypt(word1 string) string {
61+
buf := strings.Builder{}
62+
for _, b := range []byte(word1) {
63+
index, ok := this.keysMap[b]
64+
if !ok {
65+
return ""
66+
}
67+
68+
buf.WriteString(this.values[index])
69+
}
70+
return buf.String()
71+
}
72+
73+
func (this *Encrypter) search(word2 string, index int, tree *trieNode2227) int {
74+
if index >= len(word2) {
75+
if tree.end {
76+
return 1
77+
}
78+
return 0
79+
}
80+
// ab -> c, c
81+
cur := word2[index : index+2]
82+
var ret int
83+
for _, i := range this.valuesMapper[cur] {
84+
childIndex := this.keys[i] - 'a'
85+
if tree.child[childIndex] == nil {
86+
continue
87+
}
88+
ret += this.search(word2, index+2, tree.child[childIndex])
89+
}
90+
return ret
91+
}
92+
func (this *Encrypter) Decrypt(word2 string) int {
93+
return this.search(word2, 0, this.tree)
94+
}
95+
96+
func Solution(keys []byte, values []string, dictionary []string, encryptStr, decryptStr string) []any {
97+
c := Constructor(keys, values, dictionary)
98+
var ret []any
99+
ret = append(ret, c.Encrypt(encryptStr))
100+
ret = append(ret, c.Decrypt(decryptStr))
101+
return ret
5102
}

leetcode/2201-2300/2227.Encrypt-and-Decrypt-Strings/Solution_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,31 @@ import (
99
func TestSolution(t *testing.T) {
1010
// 测试用例
1111
cases := []struct {
12-
name string
13-
inputs bool
14-
expect bool
12+
name string
13+
keys []byte
14+
values, dictionary []string
15+
word1, word2 string
16+
expect []any
1517
}{
16-
{"TestCase", true, true},
17-
{"TestCase", true, true},
18-
{"TestCase", false, false},
18+
{"TestCase1", []byte{'a', 'b', 'c', 'd'}, []string{"ei", "zf", "ei", "am"}, []string{"abcd", "acbd", "adbc", "badc", "dacb", "cadb", "cbda", "abad"}, "abcd", "eizfeiam", []any{"eizfeiam", 2}},
1919
}
2020

2121
// 开始测试
2222
for i, c := range cases {
2323
t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) {
24-
got := Solution(c.inputs)
24+
got := Solution(c.keys, c.values, c.dictionary, c.word1, c.word2)
2525
if !reflect.DeepEqual(got, c.expect) {
26-
t.Fatalf("expected: %v, but got: %v, with inputs: %v",
27-
c.expect, got, c.inputs)
26+
t.Fatalf("expected: %v, but got: %v, with inputs: %v %v %v %v %v",
27+
c.expect, got, c.keys, c.values, c.dictionary, c.word1, c.word2)
2828
}
2929
})
3030
}
3131
}
3232

33-
// 压力测试
33+
// 压力测试
3434
func BenchmarkSolution(b *testing.B) {
3535
}
3636

37-
// 使用案列
37+
// 使用案列
3838
func ExampleSolution() {
3939
}

0 commit comments

Comments
 (0)