字典树力扣题目总结

 
Category: DSA

背景

前缀树, 字母树.

实现

208. 实现 Trie (前缀树);剑指 Offer II 062. 实现前缀树 - 力扣(Leetcode);

class Trie {
    Trie *next[26];
    bool is_end;

public:
    Trie() : next(), is_end(false) {
    }

    Trie *helper(string word) {
        auto cur(this);
        for (auto c : word) {
            if (!cur)
                return nullptr;
            cur = cur->next[c - 'a'];
        }
        return cur;
    }

    void insert(string word) {
        auto cur = this;
        for (auto c : word) {
            c -= 'a';
            if (!cur->next[c])
                cur->next[c] = new Trie;
            cur = cur->next[c];
        }
        cur->is_end = true; // mark word
    }

    bool search(string word) {
        auto cur = helper(word);
        return cur ? cur->is_end : false;
    }


    bool startsWith(string prefix) {
        auto cur = helper(prefix);
        return cur != nullptr;
    }
};

题目

模板题

【面试高频题】难度 2/5,字典树常规运用题;

648. 单词替换;剑指 Offer II 063. 替换单词;

class Solution {
    struct Trie {
        Trie* next[26];
        bool isEnd;
        Trie() : next(), isEnd() {}
        void add(string s) {
            auto cur(this);
            for (auto& c : s) {
                c -= 'a';
                if (!cur->next[c]) cur->next[c] = new Trie;
                cur = cur->next[c];
            }
            cur->isEnd = true;
        }
        int query(string s) { // 返回位置
            auto cur(this);
            int n = s.size();
            for (int i{}; i < n; ++i) {
                int c = s[i] - 'a';
                if (!cur->next[c]) break;
                if (cur->next[c]->isEnd) return i + 1;
                cur = cur->next[c];
            }
            return n;
        }
    };

public:
    string replaceWords(vector<string>& vs, string s) {
        Trie* root = new Trie;
        // 建树
        for (auto t : vs) root->add(t);
        stringstream ss(s);
        string ans{};
        while (ss) {
            string t;
            ss >> t;
            if (t.empty()) break;
            ans += t.substr(0, root->query(t));
            ans += ' ';
        }
        ans.pop_back();
        return ans;
    }
};

数据结构设计类

677. 键值映射;剑指 Offer II 066. 单词之和;

class MapSum {
    struct Trie {
        int val;
        Trie* next[26];
        Trie() : val(), next() {}
    };
    Trie* root;
    unordered_map<string, int> cnt;

public:
    MapSum() : root(new Trie), cnt() {}

    void insert(string key, int val) {
        int d{val};
        if (cnt.count(key)) d -= cnt[key];
        cnt[key] = val; // 更新
        auto cur(root);
        for (auto c : key) {
            c -= 'a';
            if (!cur->next[c]) cur->next[c] = new Trie;
            cur = cur->next[c];
            cur->val += d; // 前缀对应的 val 每次都更新
        }
    }

    int sum(string prefix) {
        auto cur(root);
        for (auto c : prefix) {
            c -= 'a';
            if (!cur->next[c]) return 0;
            cur = cur->next[c];
        }
        return cur->val;
    }
};

添加与搜索单词 - 数据结构设计;

其他

720. 词典中最长的单词;

1233. 删除子文件夹 - 力扣(LeetCode);