【Leetcode&C&Tire】677. Map Sum Pairs

    科技2022-08-16  97

     

    问题入口

    实现

    通过递归很好解决该问题,但是由于遍历次数过多引发了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) 

    Processed: 0.033, SQL: 9