LeetCode——677. 键值映射(Map Sum Pairs)[中等]——分析及代码(C++)

LeetCode——677. 键值映射[Map Sum Pairs][中等]——分析及代码[C++]

一、题目

实现一个 MapSum 类,支持两个方法,insert 和 sum:

  • MapSum() 初始化 MapSum 对象
  • void insert(String key, int val) 插入 key-val 键值对,字符串表示键 key ,整数表示值 val 。如果键 key 已经存在,那么原来的键值对将被替代成新的键值对。
  • int sum(string prefix) 返回所有以该前缀 prefix 开头的键 key 的值的总和。

示例:

输入:
["MapSum", "insert", "sum", "insert", "sum"]
[[], ["apple", 3], ["ap"], ["app", 2], ["ap"]]
输出:
[null, null, 3, null, 5]

解释:
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)

提示:

  • 1 <= key.length, prefix.length <= 50
  • key 和 prefix 仅由小写英文字母组成
  • 1 <= val <= 1000
  • 最多调用 50 次 insert 和 sum

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/map-sum-pairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、分析及代码

1. 字典树

(1)思路

经典的字典树应用场景,设计一棵字典树,并在节点中存储当前前缀所有对应值的和,从而在 O(n) 的时间复杂度内完成插入和查询操作(n 为待操作字符串的长度)。

为进一步在 O(1) 时间内判断 key 是否存在并获取其对应 val,可再设计一个哈希表,存储所有有效 key 及对应的 val。

(2)代码

struct TrieNode {
    
    //字典树节点
    int val;//当前前缀对应值的和
    TrieNode* next[26];//子节点
    TrieNode() {
    
    
        this->val = 0;
        for (int i = 0; i < 26; i++) {
    
    
            next[i] = nullptr;
        }
    }
};

class MapSum {
    
    
private:
    TrieNode* root;//字典树根节点
    unordered_map<string, int> nodes;//哈希表,记录已有的key和val

public:
    MapSum() {
    
    
        this->root = new TrieNode();//初始化根节点
    }
    
    void insert(string key, int val) {
    
    
        int num = val;//各前缀对应和需变化的差值
        if (nodes.count(key)) {
    
    //如果键key已存在,本次更新需减去已添加过的值
            num -= nodes[key];
        }
        nodes[key] = val;//记录已有的key和val

        //更新前缀树
        TrieNode* node = root;
        for (int i = 0; i < key.size(); i++) {
    
    //逐层更新
            if (node->next[key[i] - 'a'] == nullptr) {
    
    
                node->next[key[i] - 'a'] = new TrieNode();
            }
            node = node->next[key[i] - 'a'];
            node->val += num;
        }
        return;
    }
    
    int sum(string prefix) {
    
    
        TrieNode* node = root;
        for (int i = 0; i < prefix.size(); i++) {
    
    //逐层寻找前缀
            if (node->next[prefix[i] - 'a'] == nullptr) {
    
    //前缀不存在
                return 0;
            }
            node = node->next[prefix[i] - 'a'];
        }
        return node->val;
    }
};

/**
 * Your MapSum object will be instantiated and called as such:
 * MapSum* obj = new MapSum();
 * obj->insert(key,val);
 * int param_2 = obj->sum(prefix);
 */

(3)结果

执行用时 :4 ms,在所有 C++ 提交中击败了 73.48% 的用户;
内存消耗 :8 MB,在所有 C++ 提交中击败了 37.61% 的用户。

三、其他

暂无。

おすすめ

転載: blog.csdn.net/zml66666/article/details/121326881