前缀树

对于树的每个节点使用一个数组记录每个字母的子树,并用布尔变量判断是否为叶节点。通过深度遍历寻找对应的子树

  1. class Trie {
  2. private:
  3. vector<Trie*> children;
  4. bool isEnd;
  5. Trie* searchPrefix(string prefix){
  6. Trie* node = this;
  7. for (char ch:prefix){
  8. ch -= 'a';
  9. if(node->children[ch] == NULL)
  10. return NULL;
  11. node = node->children[ch];
  12. }
  13. return node;
  14. }
  15. public:
  16. /** Initialize your data structure here. */
  17. Trie(): children(26), isEnd(false) {
  18. }
  19. /** Inserts a word into the trie. */
  20. void insert(string word) {
  21. Trie* node = this;
  22. for (char c: word){
  23. char ch = c - 'a';
  24. if (node->children[ch] == NULL)
  25. node->children[ch] = new Trie();
  26. node = node->children[ch];
  27. }
  28. node->isEnd = true;
  29. }
  30. /** Returns if the word is in the trie. */
  31. bool search(string word) {
  32. Trie* node = this->searchPrefix(word);
  33. return node != nullptr && node->isEnd;
  34. }
  35. /** Returns if there is any word in the trie that starts with the given prefix. */
  36. bool startsWith(string prefix) {
  37. return this->searchPrefix(prefix) != nullptr;
  38. }
  39. };

LRU缓存机制

同时使用双向链表与哈希map,通过hash快速查找每个节点,使节点后放入头部,插入节点时考查是否超越容量,否则删除尾部

  1. struct DLinkedNode {
  2. int key, value;
  3. DLinkedNode* prev;
  4. DLinkedNode* next;
  5. DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}
  6. DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
  7. };
  8. class LRUCache {
  9. private:
  10. unordered_map<int, DLinkedNode*> cache;
  11. DLinkedNode* head;
  12. DLinkedNode* tail;
  13. int size;
  14. int capacity;
  15. public:
  16. LRUCache(int _capacity): capacity(_capacity), size(0) {
  17. // 使用伪头部和伪尾部节点
  18. head = new DLinkedNode();
  19. tail = new DLinkedNode();
  20. head->next = tail;
  21. tail->prev = head;
  22. }
  23. int get(int key) {
  24. if (!cache.count(key)) {
  25. return -1;
  26. }
  27. // 如果 key 存在,先通过哈希表定位,再移到头部
  28. DLinkedNode* node = cache[key];
  29. moveToHead(node);
  30. return node->value;
  31. }
  32. void put(int key, int value) {
  33. if (!cache.count(key)) {
  34. // 如果 key 不存在,创建一个新的节点
  35. DLinkedNode* node = new DLinkedNode(key, value);
  36. // 添加进哈希表
  37. cache[key] = node;
  38. // 添加至双向链表的头部
  39. addToHead(node);
  40. ++size;
  41. if (size > capacity) {
  42. // 如果超出容量,删除双向链表的尾部节点
  43. DLinkedNode* removed = removeTail();
  44. // 删除哈希表中对应的项
  45. cache.erase(removed->key);
  46. // 防止内存泄漏
  47. delete removed;
  48. --size;
  49. }
  50. }
  51. else {
  52. // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
  53. DLinkedNode* node = cache[key];
  54. node->value = value;
  55. moveToHead(node);
  56. }
  57. }
  58. void addToHead(DLinkedNode* node) {
  59. node->prev = head;
  60. node->next = head->next;
  61. head->next->prev = node;
  62. head->next = node;
  63. }
  64. void removeNode(DLinkedNode* node) {
  65. node->prev->next = node->next;
  66. node->next->prev = node->prev;
  67. }
  68. void moveToHead(DLinkedNode* node) {
  69. removeNode(node);
  70. addToHead(node);
  71. }
  72. DLinkedNode* removeTail() {
  73. DLinkedNode* node = tail->prev;
  74. removeNode(node);
  75. return node;
  76. }
  77. };
  78. /**
  79. * Your LRUCache object will be instantiated and called as such:
  80. * LRUCache* obj = new LRUCache(capacity);
  81. * int param_1 = obj->get(key);
  82. * obj->put(key,value);
  83. */

平衡二叉树

  1. struct Node {
  2. int val;
  3. Node * parent;
  4. Node * left;
  5. Node * right;
  6. int size;
  7. int height;
  8. Node(int val) {
  9. this->val = val;
  10. this->parent = nullptr;
  11. this->left = nullptr;
  12. this->right = nullptr;
  13. this->height = 0; // 结点高度:以node为根节点的子树的高度(高度定义:叶结点的高度是0)
  14. this->size = 1; // 结点元素数:以node为根节点的子树的节点总数
  15. }
  16. Node(int val, Node * parent) {
  17. this->val = val;
  18. this->parent = parent;
  19. this->left = nullptr;
  20. this->right = nullptr;
  21. this->height = 0; // 结点高度:以node为根节点的子树的高度(高度定义:叶结点的高度是0)
  22. this->size = 1; // 结点元素数:以node为根节点的子树的节点总数
  23. }
  24. Node(int val, Node * parent, Node * left, Node * right) {
  25. this->val = val;
  26. this->parent = parent;
  27. this->left = left;
  28. this->right = right;
  29. this->height = 0; // 结点高度:以node为根节点的子树的高度(高度定义:叶结点的高度是0)
  30. this->size = 1; // 结点元素数:以node为根节点的子树的节点总数
  31. }
  32. };
  33. // 平衡二叉搜索树(AVL树):允许重复值
  34. class AVL {
  35. public:
  36. AVL(vector<int> & vals) {
  37. if (!vals.empty()) {
  38. root = build(vals, 0, vals.size() - 1, nullptr);
  39. }
  40. }
  41. // 根据vals[l:r]构造平衡二叉搜索树 -> 返回根结点
  42. Node * build(vector<int> & vals, int l, int r, Node * parent) {
  43. int m = (l + r) >> 1;
  44. Node * node = new Node(vals[m], parent);
  45. if (l <= m - 1) {
  46. node->left = build(vals, l, m - 1, node);
  47. }
  48. if (m + 1 <= r) {
  49. node->right = build(vals, m + 1, r, node);
  50. }
  51. recompute(node);
  52. return node;
  53. }
  54. // 返回二叉搜索树中第k小的元素
  55. int kthSmallest(int k) {
  56. Node * node = root;
  57. while (node != nullptr) {
  58. int left = getSize(node->left);
  59. if (left < k - 1) {
  60. node = node->right;
  61. k -= left + 1;
  62. } else if (left == k - 1) {
  63. break;
  64. } else {
  65. node = node->left;
  66. }
  67. }
  68. return node->val;
  69. }
  70. void insert(int v) {
  71. if (root == nullptr) {
  72. root = new Node(v);
  73. } else {
  74. // 计算新结点的添加位置
  75. Node * node = subtreeSearch(root, v);
  76. bool isAddLeft = v <= node->val; // 是否将新结点添加到node的左子结点
  77. if (node->val == v) { // 如果值为v的结点已存在
  78. if (node->left != nullptr) { // 值为v的结点存在左子结点,则添加到其左子树的最右侧
  79. node = subtreeLast(node->left);
  80. isAddLeft = false;
  81. } else { // 值为v的结点不存在左子结点,则添加到其左子结点
  82. isAddLeft = true;
  83. }
  84. }
  85. // 添加新结点
  86. Node * leaf = new Node(v, node);
  87. if (isAddLeft) {
  88. node->left = leaf;
  89. } else {
  90. node->right = leaf;
  91. }
  92. rebalance(leaf);
  93. }
  94. }
  95. // 删除值为v的结点 -> 返回是否成功删除结点
  96. bool Delete(int v) {
  97. if (root == nullptr) {
  98. return false;
  99. }
  100. Node * node = subtreeSearch(root, v);
  101. if (node->val != v) { // 没有找到需要删除的结点
  102. return false;
  103. }
  104. // 处理当前结点既有左子树也有右子树的情况
  105. // 若左子树比右子树高度低,则将当前结点替换为右子树最左侧的结点,并移除右子树最左侧的结点
  106. // 若右子树比左子树高度低,则将当前结点替换为左子树最右侧的结点,并移除左子树最右侧的结点
  107. if (node->left != nullptr && node->right != nullptr) {
  108. Node * replacement = nullptr;
  109. if (node->left->height <= node->right->height) {
  110. replacement = subtreeFirst(node->right);
  111. } else {
  112. replacement = subtreeLast(node->left);
  113. }
  114. node->val = replacement->val;
  115. node = replacement;
  116. }
  117. Node * parent = node->parent;
  118. Delete(node);
  119. rebalance(parent);
  120. return true;
  121. }
  122. private:
  123. Node * root;
  124. // 删除结点p并用它的子结点代替它,结点p至多只能有1个子结点
  125. void Delete(Node * node) {
  126. if (node->left != nullptr && node->right != nullptr) {
  127. return;
  128. // throw new Exception("Node has two children");
  129. }
  130. Node * child = node->left != nullptr ? node->left : node->right;
  131. if (child != nullptr) {
  132. child->parent = node->parent;
  133. }
  134. if (node == root) {
  135. root = child;
  136. } else {
  137. Node * parent = node->parent;
  138. if (node == parent->left) {
  139. parent->left = child;
  140. } else {
  141. parent->right = child;
  142. }
  143. }
  144. node->parent = node;
  145. }
  146. // 在以node为根结点的子树中搜索值为v的结点,如果没有值为v的结点,则返回值为v的结点应该在的位置的父结点
  147. Node * subtreeSearch(Node * node, int v) {
  148. if (node->val < v && node->right != nullptr) {
  149. return subtreeSearch(node->right, v);
  150. } else if (node->val > v && node->left != nullptr) {
  151. return subtreeSearch(node->left, v);
  152. } else {
  153. return node;
  154. }
  155. }
  156. // 重新计算node结点的高度和元素数
  157. void recompute(Node * node) {
  158. node->height = 1 + max(getHeight(node->left), getHeight(node->right));
  159. node->size = 1 + getSize(node->left) + getSize(node->right);
  160. }
  161. // 从node结点开始(含node结点)逐个向上重新平衡二叉树,并更新结点高度和元素数
  162. void rebalance(Node * node) {
  163. while (node != nullptr) {
  164. int oldHeight = node->height, oldSize = node->size;
  165. if (!isBalanced(node)) {
  166. node = restructure(tallGrandchild(node));
  167. recompute(node->left);
  168. recompute(node->right);
  169. }
  170. recompute(node);
  171. if (node->height == oldHeight && node->size == oldSize) {
  172. node = nullptr; // 如果结点高度和元素数都没有变化则不需要再继续向上调整
  173. } else {
  174. node = node->parent;
  175. }
  176. }
  177. }
  178. // 判断node结点是否平衡
  179. bool isBalanced(Node * node) {
  180. return abs(getHeight(node->left) - getHeight(node->right)) <= 1;
  181. }
  182. // 获取node结点更高的子树
  183. Node * tallChild(Node * node) {
  184. if (getHeight(node->left) > getHeight(node->right)) {
  185. return node->left;
  186. } else {
  187. return node->right;
  188. }
  189. }
  190. // 获取node结点更高的子树中的更高的子树
  191. Node * tallGrandchild(Node * node) {
  192. Node * child = tallChild(node);
  193. return tallChild(child);
  194. }
  195. // 重新连接父结点和子结点(子结点允许为空)
  196. static void relink(Node * parent, Node * child, bool isLeft) {
  197. if (isLeft) {
  198. parent->left = child;
  199. } else {
  200. parent->right = child;
  201. }
  202. if (child != nullptr) {
  203. child->parent = parent;
  204. }
  205. }
  206. // 旋转操作
  207. void rotate(Node * node) {
  208. Node * parent = node->parent;
  209. Node * grandparent = parent->parent;
  210. if (grandparent == nullptr) {
  211. root = node;
  212. node->parent = nullptr;
  213. } else {
  214. relink(grandparent, node, parent == grandparent->left);
  215. }
  216. if (node == parent->left) {
  217. relink(parent, node->right, true);
  218. relink(node, parent, false);
  219. } else {
  220. relink(parent, node->left, false);
  221. relink(node, parent, true);
  222. }
  223. }
  224. // trinode操作
  225. Node * restructure(Node * node) {
  226. Node * parent = node->parent;
  227. Node * grandparent = parent->parent;
  228. if ((node == parent->right) == (parent == grandparent->right)) { // 处理需要一次旋转的情况
  229. rotate(parent);
  230. return parent;
  231. } else { // 处理需要两次旋转的情况:第1次旋转后即成为需要一次旋转的情况
  232. rotate(node);
  233. rotate(node);
  234. return node;
  235. }
  236. }
  237. // 返回以node为根结点的子树的第1个元素
  238. static Node * subtreeFirst(Node * node) {
  239. while (node->left != nullptr) {
  240. node = node->left;
  241. }
  242. return node;
  243. }
  244. // 返回以node为根结点的子树的最后1个元素
  245. static Node * subtreeLast(Node * node) {
  246. while (node->right != nullptr) {
  247. node = node->right;
  248. }
  249. return node;
  250. }
  251. // 获取以node为根结点的子树的高度
  252. static int getHeight(Node * node) {
  253. return node != nullptr ? node->height : 0;
  254. }
  255. // 获取以node为根结点的子树的结点数
  256. static int getSize(Node * node) {
  257. return node != nullptr ? node->size : 0;
  258. }
  259. };