前缀树
对于树的每个节点使用一个数组记录每个字母的子树,并用布尔变量判断是否为叶节点。通过深度遍历寻找对应的子树
class Trie {private:vector<Trie*> children;bool isEnd;Trie* searchPrefix(string prefix){Trie* node = this;for (char ch:prefix){ch -= 'a';if(node->children[ch] == NULL)return NULL;node = node->children[ch];}return node;}public:/** Initialize your data structure here. */Trie(): children(26), isEnd(false) {}/** Inserts a word into the trie. */void insert(string word) {Trie* node = this;for (char c: word){char ch = c - 'a';if (node->children[ch] == NULL)node->children[ch] = new Trie();node = node->children[ch];}node->isEnd = true;}/** Returns if the word is in the trie. */bool search(string word) {Trie* node = this->searchPrefix(word);return node != nullptr && node->isEnd;}/** Returns if there is any word in the trie that starts with the given prefix. */bool startsWith(string prefix) {return this->searchPrefix(prefix) != nullptr;}};
LRU缓存机制
同时使用双向链表与哈希map,通过hash快速查找每个节点,使节点后放入头部,插入节点时考查是否超越容量,否则删除尾部
struct DLinkedNode {int key, value;DLinkedNode* prev;DLinkedNode* next;DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}};class LRUCache {private:unordered_map<int, DLinkedNode*> cache;DLinkedNode* head;DLinkedNode* tail;int size;int capacity;public:LRUCache(int _capacity): capacity(_capacity), size(0) {// 使用伪头部和伪尾部节点head = new DLinkedNode();tail = new DLinkedNode();head->next = tail;tail->prev = head;}int get(int key) {if (!cache.count(key)) {return -1;}// 如果 key 存在,先通过哈希表定位,再移到头部DLinkedNode* node = cache[key];moveToHead(node);return node->value;}void put(int key, int value) {if (!cache.count(key)) {// 如果 key 不存在,创建一个新的节点DLinkedNode* node = new DLinkedNode(key, value);// 添加进哈希表cache[key] = node;// 添加至双向链表的头部addToHead(node);++size;if (size > capacity) {// 如果超出容量,删除双向链表的尾部节点DLinkedNode* removed = removeTail();// 删除哈希表中对应的项cache.erase(removed->key);// 防止内存泄漏delete removed;--size;}}else {// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部DLinkedNode* node = cache[key];node->value = value;moveToHead(node);}}void addToHead(DLinkedNode* node) {node->prev = head;node->next = head->next;head->next->prev = node;head->next = node;}void removeNode(DLinkedNode* node) {node->prev->next = node->next;node->next->prev = node->prev;}void moveToHead(DLinkedNode* node) {removeNode(node);addToHead(node);}DLinkedNode* removeTail() {DLinkedNode* node = tail->prev;removeNode(node);return node;}};/*** Your LRUCache object will be instantiated and called as such:* LRUCache* obj = new LRUCache(capacity);* int param_1 = obj->get(key);* obj->put(key,value);*/
平衡二叉树
struct Node {int val;Node * parent;Node * left;Node * right;int size;int height;Node(int val) {this->val = val;this->parent = nullptr;this->left = nullptr;this->right = nullptr;this->height = 0; // 结点高度:以node为根节点的子树的高度(高度定义:叶结点的高度是0)this->size = 1; // 结点元素数:以node为根节点的子树的节点总数}Node(int val, Node * parent) {this->val = val;this->parent = parent;this->left = nullptr;this->right = nullptr;this->height = 0; // 结点高度:以node为根节点的子树的高度(高度定义:叶结点的高度是0)this->size = 1; // 结点元素数:以node为根节点的子树的节点总数}Node(int val, Node * parent, Node * left, Node * right) {this->val = val;this->parent = parent;this->left = left;this->right = right;this->height = 0; // 结点高度:以node为根节点的子树的高度(高度定义:叶结点的高度是0)this->size = 1; // 结点元素数:以node为根节点的子树的节点总数}};// 平衡二叉搜索树(AVL树):允许重复值class AVL {public:AVL(vector<int> & vals) {if (!vals.empty()) {root = build(vals, 0, vals.size() - 1, nullptr);}}// 根据vals[l:r]构造平衡二叉搜索树 -> 返回根结点Node * build(vector<int> & vals, int l, int r, Node * parent) {int m = (l + r) >> 1;Node * node = new Node(vals[m], parent);if (l <= m - 1) {node->left = build(vals, l, m - 1, node);}if (m + 1 <= r) {node->right = build(vals, m + 1, r, node);}recompute(node);return node;}// 返回二叉搜索树中第k小的元素int kthSmallest(int k) {Node * node = root;while (node != nullptr) {int left = getSize(node->left);if (left < k - 1) {node = node->right;k -= left + 1;} else if (left == k - 1) {break;} else {node = node->left;}}return node->val;}void insert(int v) {if (root == nullptr) {root = new Node(v);} else {// 计算新结点的添加位置Node * node = subtreeSearch(root, v);bool isAddLeft = v <= node->val; // 是否将新结点添加到node的左子结点if (node->val == v) { // 如果值为v的结点已存在if (node->left != nullptr) { // 值为v的结点存在左子结点,则添加到其左子树的最右侧node = subtreeLast(node->left);isAddLeft = false;} else { // 值为v的结点不存在左子结点,则添加到其左子结点isAddLeft = true;}}// 添加新结点Node * leaf = new Node(v, node);if (isAddLeft) {node->left = leaf;} else {node->right = leaf;}rebalance(leaf);}}// 删除值为v的结点 -> 返回是否成功删除结点bool Delete(int v) {if (root == nullptr) {return false;}Node * node = subtreeSearch(root, v);if (node->val != v) { // 没有找到需要删除的结点return false;}// 处理当前结点既有左子树也有右子树的情况// 若左子树比右子树高度低,则将当前结点替换为右子树最左侧的结点,并移除右子树最左侧的结点// 若右子树比左子树高度低,则将当前结点替换为左子树最右侧的结点,并移除左子树最右侧的结点if (node->left != nullptr && node->right != nullptr) {Node * replacement = nullptr;if (node->left->height <= node->right->height) {replacement = subtreeFirst(node->right);} else {replacement = subtreeLast(node->left);}node->val = replacement->val;node = replacement;}Node * parent = node->parent;Delete(node);rebalance(parent);return true;}private:Node * root;// 删除结点p并用它的子结点代替它,结点p至多只能有1个子结点void Delete(Node * node) {if (node->left != nullptr && node->right != nullptr) {return;// throw new Exception("Node has two children");}Node * child = node->left != nullptr ? node->left : node->right;if (child != nullptr) {child->parent = node->parent;}if (node == root) {root = child;} else {Node * parent = node->parent;if (node == parent->left) {parent->left = child;} else {parent->right = child;}}node->parent = node;}// 在以node为根结点的子树中搜索值为v的结点,如果没有值为v的结点,则返回值为v的结点应该在的位置的父结点Node * subtreeSearch(Node * node, int v) {if (node->val < v && node->right != nullptr) {return subtreeSearch(node->right, v);} else if (node->val > v && node->left != nullptr) {return subtreeSearch(node->left, v);} else {return node;}}// 重新计算node结点的高度和元素数void recompute(Node * node) {node->height = 1 + max(getHeight(node->left), getHeight(node->right));node->size = 1 + getSize(node->left) + getSize(node->right);}// 从node结点开始(含node结点)逐个向上重新平衡二叉树,并更新结点高度和元素数void rebalance(Node * node) {while (node != nullptr) {int oldHeight = node->height, oldSize = node->size;if (!isBalanced(node)) {node = restructure(tallGrandchild(node));recompute(node->left);recompute(node->right);}recompute(node);if (node->height == oldHeight && node->size == oldSize) {node = nullptr; // 如果结点高度和元素数都没有变化则不需要再继续向上调整} else {node = node->parent;}}}// 判断node结点是否平衡bool isBalanced(Node * node) {return abs(getHeight(node->left) - getHeight(node->right)) <= 1;}// 获取node结点更高的子树Node * tallChild(Node * node) {if (getHeight(node->left) > getHeight(node->right)) {return node->left;} else {return node->right;}}// 获取node结点更高的子树中的更高的子树Node * tallGrandchild(Node * node) {Node * child = tallChild(node);return tallChild(child);}// 重新连接父结点和子结点(子结点允许为空)static void relink(Node * parent, Node * child, bool isLeft) {if (isLeft) {parent->left = child;} else {parent->right = child;}if (child != nullptr) {child->parent = parent;}}// 旋转操作void rotate(Node * node) {Node * parent = node->parent;Node * grandparent = parent->parent;if (grandparent == nullptr) {root = node;node->parent = nullptr;} else {relink(grandparent, node, parent == grandparent->left);}if (node == parent->left) {relink(parent, node->right, true);relink(node, parent, false);} else {relink(parent, node->left, false);relink(node, parent, true);}}// trinode操作Node * restructure(Node * node) {Node * parent = node->parent;Node * grandparent = parent->parent;if ((node == parent->right) == (parent == grandparent->right)) { // 处理需要一次旋转的情况rotate(parent);return parent;} else { // 处理需要两次旋转的情况:第1次旋转后即成为需要一次旋转的情况rotate(node);rotate(node);return node;}}// 返回以node为根结点的子树的第1个元素static Node * subtreeFirst(Node * node) {while (node->left != nullptr) {node = node->left;}return node;}// 返回以node为根结点的子树的最后1个元素static Node * subtreeLast(Node * node) {while (node->right != nullptr) {node = node->right;}return node;}// 获取以node为根结点的子树的高度static int getHeight(Node * node) {return node != nullptr ? node->height : 0;}// 获取以node为根结点的子树的结点数static int getSize(Node * node) {return node != nullptr ? node->size : 0;}};
