Skip to content

Commit 3c4bb50

Browse files
authored
Merge pull request ByteByteGoHq#38 from ongshunping/cpp-solutions-tries
Add C++ solutions for Chapter 12 (Tries)
2 parents 9eaa69e + 4fd2779 commit 3c4bb50

File tree

3 files changed

+214
-0
lines changed

3 files changed

+214
-0
lines changed

cpp/Tries/design_a_trie.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include <unordered_map>
2+
#include <string>
3+
4+
class TrieNode {
5+
public:
6+
std::unordered_map<char, TrieNode*> children;
7+
bool isWord;
8+
TrieNode() : isWord(false) {}
9+
~TrieNode() {
10+
for (auto& pair : children) {
11+
delete pair.second;
12+
}
13+
}
14+
};
15+
16+
class Trie {
17+
public:
18+
Trie() {
19+
root = new TrieNode();
20+
}
21+
22+
~Trie() {
23+
delete root;
24+
}
25+
26+
void insert(std::string word) {
27+
TrieNode* node = root;
28+
for (char c : word) {
29+
// For each character in the word, if it's not a child of
30+
// the current node, create a new TrieNode for that
31+
// character.
32+
if (node->children.find(c) == node->children.end()) {
33+
node->children[c] = new TrieNode();
34+
}
35+
node = node->children[c];
36+
}
37+
// Mark the last node as the end of a word.
38+
node->isWord = true;
39+
}
40+
41+
bool search(std::string word) {
42+
TrieNode* node = root;
43+
for (char c : word) {
44+
// For each character in the word, if it's not a child of
45+
// the current node, the word doesn't exist in the Trie.
46+
if (node->children.find(c) == node->children.end()) {
47+
return false;
48+
}
49+
node = node->children[c];
50+
}
51+
// Return whether the current node is marked as the end of the
52+
// word.
53+
return node->isWord;
54+
}
55+
56+
bool hasPrefix(std::string prefix) {
57+
TrieNode* node = root;
58+
for (char c : prefix) {
59+
if (node->children.find(c) == node->children.end()) {
60+
return false;
61+
}
62+
node = node->children[c];
63+
}
64+
// Once we've traversed the nodes corresponding to each
65+
// character in the prefix, return True.
66+
return true;
67+
}
68+
69+
private:
70+
TrieNode* root;
71+
};
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include <unordered_map>
2+
#include <vector>
3+
#include <string>
4+
5+
class TrieNode {
6+
public:
7+
std::unordered_map<char, TrieNode*> children;
8+
std::string word;
9+
TrieNode() : word("") {}
10+
~TrieNode() {
11+
for (auto& pair : children) {
12+
delete pair.second;
13+
}
14+
}
15+
};
16+
17+
std::vector<std::string> findAllWordsOnABoard(std::vector<std::vector<char>>& board, std::vector<std::string>& words) {
18+
TrieNode* root = new TrieNode();
19+
// Insert every word into the trie.
20+
for (std::string& word : words) {
21+
TrieNode* node = root;
22+
for (char c : word) {
23+
if (node->children.find(c) == node->children.end()) {
24+
node->children[c] = new TrieNode();
25+
}
26+
node = node->children[c];
27+
}
28+
node->word = word;
29+
}
30+
std::vector<std::string> res;
31+
// Start a DFS call from each cell of the board that contains a
32+
// child of the root node, which represents the first letter of a
33+
// word in the trie.
34+
int rows = board.size();
35+
int cols = board[0].size();
36+
for (int r = 0; r < rows; r++) {
37+
for (int c = 0; c < cols; c++) {
38+
if (root->children.find(board[r][c]) != root->children.end()) {
39+
dfs(board, r, c, root->children[board[r][c]], res);
40+
}
41+
}
42+
}
43+
delete root;
44+
return res;
45+
}
46+
47+
void dfs(std::vector<std::vector<char>>& board, int r, int c, TrieNode* node, std::vector<std::string>& res) {
48+
// If the current node represents the end of a word, add the word to
49+
// the result.
50+
if (!node->word.empty()) {
51+
res.push_back(node->word);
52+
// Ensure the current word is only added once.
53+
node->word = "";
54+
}
55+
char temp = board[r][c];
56+
// Mark the current cell as visited.
57+
board[r][c] = '#';
58+
// Explore all adjacent cells that correspond with a child of the
59+
// current TrieNode.
60+
std::vector<std::pair<int, int>> dirs = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
61+
for (auto& dir : dirs) {
62+
int next_r = r + dir.first;
63+
int next_c = c + dir.second;
64+
if (isWithinBounds(next_r, next_c, board) &&
65+
node->children.find(board[next_r][next_c]) != node->children.end()) {
66+
dfs(board, next_r, next_c, node->children[board[next_r][next_c]], res);
67+
}
68+
}
69+
// Backtrack by reverting the cell back to its original character.
70+
board[r][c] = temp;
71+
}
72+
73+
bool isWithinBounds(int r, int c, std::vector<std::vector<char>>& board) {
74+
return r >= 0 && r < board.size() && c >= 0 && c < board[0].size();
75+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <unordered_map>
2+
#include <string>
3+
4+
class TrieNode {
5+
public:
6+
std::unordered_map<char, TrieNode*> children;
7+
bool isWord;
8+
TrieNode() : isWord(false) {}
9+
~TrieNode() {
10+
for (auto& pair : children) {
11+
delete pair.second;
12+
}
13+
}
14+
};
15+
16+
class InsertAndSearchWordsWithWildcards {
17+
public:
18+
InsertAndSearchWordsWithWildcards() {
19+
root = new TrieNode();
20+
}
21+
22+
~InsertAndSearchWordsWithWildcards() {
23+
delete root;
24+
}
25+
26+
void insert(std::string word) {
27+
TrieNode* node = root;
28+
for (char c : word) {
29+
if (node->children.find(c) == node->children.end()) {
30+
node->children[c] = new TrieNode();
31+
}
32+
node = node->children[c];
33+
}
34+
node->isWord = true;
35+
}
36+
37+
bool search(std::string word) {
38+
// Start searching from the root of the trie.
39+
return searchHelper(0, word, root);
40+
}
41+
42+
private:
43+
TrieNode* root;
44+
45+
bool searchHelper(int wordIndex, std::string word, TrieNode* node) {
46+
for (int i = wordIndex; i < word.length(); i++) {
47+
char c = word[i];
48+
// If a wildcard character is encountered, recursively
49+
// search for the rest of the word from each child node.
50+
if (c == '.') {
51+
for (auto& pair : node->children) {
52+
// If a match is found, return true.
53+
if (searchHelper(i + 1, word, pair.second)) {
54+
return true;
55+
}
56+
}
57+
return false;
58+
} else if (node->children.find(c) != node->children.end()) {
59+
node = node->children[c];
60+
} else {
61+
return false;
62+
}
63+
}
64+
// After processing the last character, return true if we've
65+
// reached the end of a word.
66+
return node->isWord;
67+
}
68+
};

0 commit comments

Comments
 (0)