Map Sum Pairs LeetCode Solution using Trie and DFS
Published in
3 min readJul 30, 2021
A nice problem can be solved by using Trie, DFS, and a hash table.
677. Map Sum Pairs
You need to Design a map that allows you to do the following:
- Maps a string key to a given value.
- Returns the sum of the values that have a key with a prefix equal to a given string.
Implement the MapSum
class:
MapSum()
Initializes theMapSum
object.void insert(String key, int val)
Inserts thekey-val
pair into the map. If thekey
already existed, the originalkey-value
pair will be overridden to the new one.int sum(string prefix)
Returns the sum of all the pairs' value whosekey
starts with theprefix
.
Example 1:
Input
["MapSum", "insert", "sum", "insert", "sum"]
[[], ["apple", 3], ["ap"], ["app", 2], ["ap"]]
Output
[null, null, 3, null, 5]Explanation
MapSum mapSum = new MapSum();
mapSum.insert("apple", 3);
mapSum.sum("ap"); // return 3 (apple = 3)
mapSum.insert("app", 2);
mapSum.sum("ap"); // return 5 (apple + app = 3 + 2 = 5)
Constraints:
1 <= key.length, prefix.length <= 50
key
andprefix
consist of only lowercase English letters.1 <= val <= 1000
- At most
50
calls will be made toinsert
andsum
.
Reference Code
struct TrieNode{
public:
bool is_word = false;
vector<TrieNode*> children;
TrieNode(){
children.assign(26, nullptr);
}
};
class MapSum {
public:
unordered_map<string, int> m;
TrieNode* root;
/** Initialize your data structure here. */
MapSum() {
root = new TrieNode();
}
void insert(string key, int val) {
if (m.find(key) != m.end()) {
m[key] = val;
return;
}
m[key] = val;
// insert this word to TrieNode
auto node = root;
const int n = key.size();
for (int i = 0; i < n; ++i){
int ch_idx = key[i] - 'a';
if (node -> children[ch_idx] == nullptr){
node -> children[ch_idx] = new TrieNode();
}
node = node -> children[ch_idx];
if (i == n - 1) node -> is_word = true;
}
return;
}
int dfs(TrieNode* node, string prefix){
int ret = 0;
if (node -> is_word) ret += m[prefix];
for (char ch = 'a'; ch <= 'z'; ch++){
if (node -> children[ch - 'a'] != nullptr){
ret += dfs(node -> children[ch - 'a'], prefix + ch);
}
}
return ret;
}
int sum(string prefix) {
auto node = root;
for (int i = 0; i < prefix.size(); ++i){
int ch_idx = prefix[i] - 'a';
if (node -> children[ch_idx] == nullptr) return 0;
node = node -> children[ch_idx];
}
return dfs(node, prefix);
}
};
/**
* Your MapSum object will be instantiated and called as such:
* MapSum* obj = new MapSum();
* obj->insert(key,val);
* int param_2 = obj->sum(prefix);
*/
Problem
Solution
struct TrieNode{
public:
bool is_word = false;
vector<TrieNode*> children;
TrieNode(){
children.assign(26, nullptr);
}
};
class Trie{
public:
TrieNode* root;
Trie(){
root = new TrieNode();
}
void insert(string &word){
if (word.empty())return;
auto curr = root;
for (auto c: word){
int idx = c - 'a';
if (curr->children[idx] == nullptr){
curr->children[idx] = new TrieNode();
}
curr = curr->children[idx];
}
curr -> is_word = true;
}
};
class Solution {
public:
unordered_map<string, int> memo;
int dfs(int i, string& word, TrieNode* node){
string sub_str = word.substr(i);
if (memo.find(sub_str) !=memo.end())return memo[sub_str];
if (i == word.size()){
return memo[sub_str] = 0;
}
auto curr = node;
int max_words = -1;
for (int j = i; j < (int) word.size(); ++j){
curr = curr->children[word[j] - 'a'];
if (curr == nullptr)break;
if (curr -> is_word){
int this_ret = dfs(j + 1, word, node);
if (this_ret == -1) continue;
else {
max_words = max(max_words, 1 + this_ret);
}
}
}
return memo[sub_str] = max_words;
}
vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
Trie trie;
for (auto &word: words){
trie.insert(word);
}
vector<string> ret;
for (auto &word: words){
int num_of_concat_words = dfs(0, word, trie.root);
if (num_of_concat_words >= 2){
ret.push_back(word);
}
}
return ret;
}
};