实现
通过递归很好解决该问题,但是由于遍历次数过多引发了Runtime Error(ps:这是用C语言编写的情况下),所以需要寻找其他解决方法。
在我原本使用递归思路解决问题时,我对MapSum结构体定义如下:
struct MapSum{
MapSum **next;
int value;
};
value>0(题目给的值都是正数)就表达了这个单词的值 ,同时也说明这是单词的结尾。等于一个属性参与了两个动作。
如果我把每次加入的值都加在每一个字母上又会如何呢?
例如,进行如下操作
Input: insert("apple", 3), Output: Null
Input: sum("ap"), Output: 3
Input: insert("app", 2), Output: Null
Input: sum("ap"), Output: 5
可以看到第二次加入的app,对应的三个字母的值都是5。这样sum操作就仅是通过for循环到达第二个p的位置 ,返回value即可。
然而如果是更新操作,值会叠加,不会更新。
Input: insert("apple", 3), Output: Null
Input: sum("ap"), Output: 3
Input: insert("apple", 2), Output: Null
Input: sum("ap"), Output: 5 // incorrect, the answer is 2
对于更新操作,我们需要再遍历一次Tire树减去之前的value ——即添加后的value-形参value。另外,结构体MapSum需要添加一个属性bool isWord。因为此时的value是用来表现包含这个字母的值的总和,它不具备判断是否是一个单词的语义。而isWord可以判断是进行添加操作还是更新操作。如果isWord为true,证明这是更新操作,我们需要减去之前的value;如果isWord为false, 证明这是增加操作。
#define LEN 26
typedef struct MapSum MapSum;
struct MapSum{
MapSum **next;
int value;
bool isWord;
};/** Initialize your data structure here. */
MapSum* mapSumCreate() {
MapSum *ms = malloc(sizeof(MapSum));
int space = sizeof(MapSum*)*LEN;
ms->next = malloc(space);
memset(ms->next,0,space);
ms->value = 0;
ms->isWord=false;
return ms;
}void updateValue(MapSum* obj, char *key,int val){
for(int i=0;key[i]!='\0';i++){
int nIndex=key[i]-'a';
obj=obj->next[nIndex];
obj->value+=val;
}
}void mapSumInsert(MapSum* obj, char * key, int val) {
MapSum *root = obj;
for(int i=0;key[i]!='\0';i++){
int nIndex = key[i]-'a';
if(!(obj->next[nIndex]))
obj->next[nIndex]=mapSumCreate();
obj=obj->next[nIndex];
obj->value+=val;
}
if(obj->isWord)
updateValue(root,key,-1*(obj->value-val));
obj->isWord=true;
}
int mapSumSum(MapSum* obj, char * prefix) {
for(int i=0;prefix[i]!='\0';i++){
int nIndex = prefix[i]-'a';
if(obj->next[nIndex])
obj=obj->next[prefix[i]-'a'];
else
return NULL;
}
return obj->value;
}void mapSumFree(MapSum* obj) {
free(obj->next);
free(obj);
}/**
* Your MapSum struct will be instantiated and called as such:
* MapSum* obj = mapSumCreate();
* mapSumInsert(obj, key, val);
* int param_2 = mapSumSum(obj, prefix);
* mapSumFree(obj);
*/
最后来分析一下时间复杂度。假设添加的单词有n个字符,查找的前缀有k个字符。那么增加操作的时间复杂度为O(n),查找操作的时间复杂度为O(k)