leetcode设计类题目——677. 键值映射

Posted C_YCBX Py_YYDS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode设计类题目——677. 键值映射相关的知识,希望对你有一定的参考价值。

题目


OJ平台

需求分析

需求:

  1. 插入单词与值形成联系
  2. 查询前缀对应的所有单词的值的和
  • 很明显,直接用字典树便可完成这个需求。

但有一个问题:如何快速得到这个前缀对应的所有单词的和?

很简单的处理方式就是利用哈希表对每个单词的权值进行记录 ,如果出现替换键值映射的情况,那就将这次的加和值减去原来的值。

当然也可不用哈希表,直接多设置一个 f 标记用于区分单词结尾,顺便记录这个单词对应的权值,如果出现键值替换的情况,直接就将这个值从头再减去一遍即可。

代码部分

解题代码:

struct str{//用于标记是否存在这个单词,且保存它对应的权值
    int v;
    str(int v):v(v){}
};

struct node{//字典树的结点
    str* f;
    int w;
    node* next[26];
    node(int w):w(w),f(nullptr){
        memset(next,0,sizeof(node*)*26);
    }
};

class MapSum {
public:
    node* head;
    MapSum() {
        head = new node(0);
    }

    void insert(string key, int val) {
        //思路很简单,就是插入的时候把经过的路径上加上之前的带权值
        int pos;
        node* root = head;
        for(auto&& ch:key){
                pos = ch-'a';
            if(root->next[pos] == 0){
                root->next[pos] = new node(val);
            }else{
                root->next[pos]->w += val;
            }
            root = root->next[pos];
        }

        if(root->f){//如果这个键值已经存在,则往回减去这个 v 值
            int _val = root->f->v;
            node* _root = head;
            for(auto&&ch : key){
                pos = ch-'a';
                _root->next[pos]->w -= _val;
                _root = _root->next[pos];
            }
            _root->f->v = val;
        }else{
            root->f = new str(val);
        }
    }
    int sum(string prefix) {
        node* root = head;
        for(auto&& ch: prefix){//由于w直接就记录了整个带权路径和,所以只要找到prefix的终点即可
            if(root->next[ch-'a']!=0)
                root = root->next[ch-'a'];
            else
                return 0;
        }
        return root->w;
    }
};

工业化代码:

struct str{//用于标记是否存在这个单词,且保存它对应的权值
    int v;
    str(int v):v(v){}
};

struct node{//字典树的结点
    str* f;
    int w;
    node* next[26];
    node(int w):w(w),f(nullptr){
        memset(next,0,sizeof(node*)*26);
    }
};

class MapSum {
private:
    void destroy(node* root){
        if(!root)
            return;
        for(int i=0;i<26;i++){
            if(root->next[i]){
                destroy(root->next[i]);
            }
        }
        if(root->f)
            delete root->f;
        delete root;
    }
public:
    node* head;
    MapSum() {
        head = new node(0);
    }
    ~MapSum() {
        destroy(head);
    }
    
    void insert(string key, int val) {
        //思路很简单,就是插入的时候把经过的路径上加上之前的带权值
        int pos;
        node* root = head;
        for(auto&& ch:key){
                pos = ch-'a';

            assert(root != 0); //老师说工业界代码要加几个断言

            if(root->next[pos] == 0){
                root->next[pos] = new node(val);
            }else{
                root->next[pos]->w += val;
            }
            root = root->next[pos];
        }

        if(root->f){//如果这个键值已经存在,则往回减去这个 v 值
            int _val = root->f->v;
            node* _root = head;
            for(auto&&ch : key){
                pos = ch-'a';
                _root->next[pos]->w -= _val;
                _root = _root->next[pos];
            }
            _root->f->v = val;
        }else{
            root->f = new str(val);
        }
    }
    int sum(string prefix) {
        node* root = head;
        for(auto&& ch: prefix){//由于w直接就记录了整个带权路径和,所以只要找到prefix的终点即可
            assert(root != 0);
            if(root->next[ch-'a']!=0)
                root = root->next[ch-'a'];
            else
                return 0;
        }
        return root->w;
    }
};

以上是关于leetcode设计类题目——677. 键值映射的主要内容,如果未能解决你的问题,请参考以下文章

[677]. 键值映射

[677]. 键值映射

LeetCode 520. 检测大写字母 / 677. 键值映射 / 319. 灯泡开关

LeetCode 677 键值映射[Map] HERODING的LeetCode之路

LeetCode677. 键值映射(相关话题:Trie前缀树)

LeetCode677. 键值映射(相关话题:Trie前缀树)