677. Map Sum Pairs(python+cpp)(包含前缀树解法)

题目:

Implement a MapSum class with insert, and sum methods.
For the method insert, you’ll be given a pair of (string, integer).The string represents the key and the integer represents the value. If the key already existed, then the original key-value pair will be overridden to the new one.
For the method sum, you’ll be given a string representing the prefix,and you need to return the sum of all the pairs’ value whose key starts with the prefix.
Example 1:

Input: insert("apple", 3), Output: Null 
Input: sum("ap"), Output: 3 
Input: insert("app", 2), Output: Null 
Input: sum("ap"), Output: 5

解释:
这题可以用字典做,但是更经典的解法是Trie
字典解法,
1.在插入时直接插入,在求和是查询所有前缀,插入快
2.也可以在插入的时候记入所有前缀,查询快。
3.前缀树解法
第一种解法在c++中,可以利用map对key排序的特点,map.lower_bound(prefix)就可以得到可能以prefix为前缀的最小键值对,然后从这里开始遍历,满足条件便将其累加,不满足条件则可以终止遍历。最后return累加值。
解法一:
python代码:

class MapSum(object):
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self._dict={}
    def insert(self, key, val):
        """
        :type key: str
        :type val: int
        :rtype: void
        """
        self._dict[key]=val  
    def sum(self, prefix):
        """
        :type prefix: str
        :rtype: int
        """
        result=0
        for key in self._dict.keys():
            if key.find(prefix)==0:
                result+=self._dict[key]
        return result
# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)

c++代码:

#include <map>
using namespace std;
class MapSum {
public:
    /** Initialize your data structure here. */
    map<string,int>_map;
    MapSum() { 
    }
    void insert(string key, int val) {
        _map[key]=val;
    }
    int sum(string prefix) {
        int _sum=0;
        for (auto it = _map.lower_bound(prefix); it != _map.end();it++){
            if (it->first.find(prefix)==0)
                _sum += it->second;
        }
        return _sum;
    }
};
/**
 * Your MapSum object will be instantiated and called as such:
 * MapSum obj = new MapSum();
 * obj.insert(key,val);
 * int param_2 = obj.sum(prefix);
 */

判断key是否以prefix开头也可以用以下代码:

int sum = 0, len = prefix.size();
for (auto it = m.lower_bound(prefix); it != m.end();++it){
    if (it->first.substr(0,len) == prefix) 
    	sum += it->second;
}
return sum;

一个是查询字符串开始的位置,一个是从同一开始取指定长度的子字符串看是否相等。
解法2:
python代码:

class MapSum(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self._dict={}
        self._sum={}
    def insert(self, key, val):
        """
        :type key: str
        :type val: int
        :rtype: void
        """
        diff=val-self._dict.get(key,0)
        for i in range(0,len(key)):
            sub=key[:i+1]
            self._sum[sub]=self._sum.get(sub,0)+diff
        self._dict[key] =val
    def sum(self, prefix):
        """
        :type prefix: str
        :rtype: int
        """
        return self._sum.get(prefix,0)
# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)

c++代码(速度没有解法1快):

#include <map>
using namespace std;
class MapSum {
public:
    /** Initialize your data structure here. */
    map<string ,int>_map;
    map<string ,int>_sum;
    MapSum() {
    }
    void insert(string key, int val) {
        int diff=val-_map[key];
        for (int i=0;i<key.size();i++)
        {
            string sub=key.substr(0,i+1);
            _sum[sub]+=diff;
        }
        _map[key]=val;
    }
    int sum(string prefix) {
        return _sum[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);
 */

前缀树解法:

#感觉这道题是经典的字典树问题
from collections import defaultdict
class TrieNode(object):
    def __init__(self):
        self.children=defaultdict(TrieNode)
        self.isWord=False
        self.freq=0
        
class MapSum(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.root=TrieNode()
        self._dict={}
        
    def insert(self, key, val):
        """
        :type key: str
        :type val: int
        :rtype: void
        """
        current=self.root
        for letter in key:
            current=current.children[letter]
            current.freq+=val-self._dict.get(key,0)
        current.isWord=True
        self._dict[key]=val
        
    def sum(self, prefix):
        """
        :type prefix: str
        :rtype: int
        """
        current =self.root
        for letter in prefix:
            current=current.children.get(letter)
            if current==None:
                return 0
        return current.freq

# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)

c++代码:

#include <map>
using namespace std;
struct TrieNode{
    bool isWord;
    map<char,TrieNode*>children;
    int freq;
    TrieNode():isWord(false),freq(0) {};
};
class MapSum {
public:
    /** Initialize your data structure here. */
    TrieNode *root;
    map<string,int>visited;
    MapSum() {
        root=new TrieNode();
    }
    
    void insert(string key, int val) {
        TrieNode* current=root;
        for(auto letter:key)
        {
            if (!current->children.count(letter))
                current->children[letter]=new TrieNode();
            current=current->children[letter];
            current->freq+=val-visited[key];
        }
        current->isWord=true;
        visited[key]=val;
    }
    
    int sum(string prefix) {
        TrieNode* current=root;
        for(auto letter:prefix)
        {
            if (!current->children.count(letter))
                return 0;
            current=current->children[letter];
            
        }
        return current->freq;
    }
};

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

总结:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值