diff --git a/solution/0000-0099/0023.Merge k Sorted Lists/README.md b/solution/0000-0099/0023.Merge k Sorted Lists/README.md index c07f16ad90222..d06143c55db86 100644 --- a/solution/0000-0099/0023.Merge k Sorted Lists/README.md +++ b/solution/0000-0099/0023.Merge k Sorted Lists/README.md @@ -232,11 +232,7 @@ func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; function mergeKLists(lists: Array): ListNode | null { const pq = new MinPriorityQueue({ priority: (node: ListNode) => node.val }); - for (const head of lists) { - if (head) { - pq.enqueue(head); - } - } + lists.filter(head => head).forEach(head => pq.enqueue(head)); const dummy: ListNode = new ListNode(); let cur: ListNode = dummy; while (!pq.isEmpty()) { @@ -318,11 +314,7 @@ impl Solution { */ var mergeKLists = function (lists) { const pq = new MinPriorityQueue({ priority: node => node.val }); - for (const head of lists) { - if (head) { - pq.enqueue(head); - } - } + lists.filter(head => head).forEach(head => pq.enqueue(head)); const dummy = new ListNode(); let cur = dummy; while (!pq.isEmpty()) { diff --git a/solution/0000-0099/0023.Merge k Sorted Lists/README_EN.md b/solution/0000-0099/0023.Merge k Sorted Lists/README_EN.md index c202848462f5a..e7e07e00330c5 100644 --- a/solution/0000-0099/0023.Merge k Sorted Lists/README_EN.md +++ b/solution/0000-0099/0023.Merge k Sorted Lists/README_EN.md @@ -233,11 +233,7 @@ func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; function mergeKLists(lists: Array): ListNode | null { const pq = new MinPriorityQueue({ priority: (node: ListNode) => node.val }); - for (const head of lists) { - if (head) { - pq.enqueue(head); - } - } + lists.filter(head => head).forEach(head => pq.enqueue(head)); const dummy: ListNode = new ListNode(); let cur: ListNode = dummy; while (!pq.isEmpty()) { @@ -319,11 +315,7 @@ impl Solution { */ var mergeKLists = function (lists) { const pq = new MinPriorityQueue({ priority: node => node.val }); - for (const head of lists) { - if (head) { - pq.enqueue(head); - } - } + lists.filter(head => head).forEach(head => pq.enqueue(head)); const dummy = new ListNode(); let cur = dummy; while (!pq.isEmpty()) { diff --git a/solution/0000-0099/0023.Merge k Sorted Lists/Solution.js b/solution/0000-0099/0023.Merge k Sorted Lists/Solution.js index d6f1c7d4451db..d08377efe3a0b 100644 --- a/solution/0000-0099/0023.Merge k Sorted Lists/Solution.js +++ b/solution/0000-0099/0023.Merge k Sorted Lists/Solution.js @@ -11,11 +11,7 @@ */ var mergeKLists = function (lists) { const pq = new MinPriorityQueue({ priority: node => node.val }); - for (const head of lists) { - if (head) { - pq.enqueue(head); - } - } + lists.filter(head => head).forEach(head => pq.enqueue(head)); const dummy = new ListNode(); let cur = dummy; while (!pq.isEmpty()) { diff --git a/solution/0000-0099/0023.Merge k Sorted Lists/Solution.ts b/solution/0000-0099/0023.Merge k Sorted Lists/Solution.ts index cf5c2a4ae41d8..cf00ff0f98869 100644 --- a/solution/0000-0099/0023.Merge k Sorted Lists/Solution.ts +++ b/solution/0000-0099/0023.Merge k Sorted Lists/Solution.ts @@ -12,11 +12,7 @@ function mergeKLists(lists: Array): ListNode | null { const pq = new MinPriorityQueue({ priority: (node: ListNode) => node.val }); - for (const head of lists) { - if (head) { - pq.enqueue(head); - } - } + lists.filter(head => head).forEach(head => pq.enqueue(head)); const dummy: ListNode = new ListNode(); let cur: ListNode = dummy; while (!pq.isEmpty()) { diff --git a/solution/0100-0199/0146.LRU Cache/README.md b/solution/0100-0199/0146.LRU Cache/README.md index 7bb35b178741e..8bde7e34d476a 100644 --- a/solution/0100-0199/0146.LRU Cache/README.md +++ b/solution/0100-0199/0146.LRU Cache/README.md @@ -95,7 +95,7 @@ lRUCache.get(4); // 返回 4 ```python class Node: - def __init__(self, key=0, val=0): + def __init__(self, key: int = 0, val: int = 0): self.key = key self.val = val self.prev = None @@ -103,12 +103,13 @@ class Node: class LRUCache: + def __init__(self, capacity: int): + self.size = 0 + self.capacity = capacity self.cache = {} self.head = Node() self.tail = Node() - self.capacity = capacity - self.size = 0 self.head.next = self.tail self.tail.prev = self.head @@ -116,28 +117,27 @@ class LRUCache: if key not in self.cache: return -1 node = self.cache[key] - self.move_to_head(node) + self.remove_node(node) + self.add_to_head(node) return node.val def put(self, key: int, value: int) -> None: if key in self.cache: node = self.cache[key] + self.remove_node(node) node.val = value - self.move_to_head(node) + self.add_to_head(node) else: node = Node(key, value) self.cache[key] = node self.add_to_head(node) self.size += 1 if self.size > self.capacity: - node = self.remove_tail() + node = self.tail.prev self.cache.pop(node.key) + self.remove_node(node) self.size -= 1 - def move_to_head(self, node): - self.remove_node(node) - self.add_to_head(node) - def remove_node(self, node): node.prev.next = node.next node.next.prev = node.prev @@ -148,11 +148,6 @@ class LRUCache: self.head.next = node node.next.prev = node - def remove_tail(self): - node = self.tail.prev - self.remove_node(node) - return node - # Your LRUCache object will be instantiated and called as such: # obj = LRUCache(capacity) @@ -164,10 +159,8 @@ class LRUCache: ```java class Node { - int key; - int val; - Node prev; - Node next; + int key, val; + Node prev, next; Node() { } @@ -179,11 +172,11 @@ class Node { } class LRUCache { - private Map cache = new HashMap<>(); + private int size; + private int capacity; private Node head = new Node(); private Node tail = new Node(); - private int capacity; - private int size; + private Map cache = new HashMap<>(); public LRUCache(int capacity) { this.capacity = capacity; @@ -196,33 +189,30 @@ class LRUCache { return -1; } Node node = cache.get(key); - moveToHead(node); + removeNode(node); + addToHead(node); return node.val; } public void put(int key, int value) { if (cache.containsKey(key)) { Node node = cache.get(key); + removeNode(node); node.val = value; - moveToHead(node); + addToHead(node); } else { Node node = new Node(key, value); cache.put(key, node); addToHead(node); - ++size; - if (size > capacity) { - node = removeTail(); + if (++size > capacity) { + node = tail.prev; cache.remove(node.key); + removeNode(node); --size; } } } - private void moveToHead(Node node) { - removeNode(node); - addToHead(node); - } - private void removeNode(Node node) { node.prev.next = node.next; node.next.prev = node.prev; @@ -234,12 +224,6 @@ class LRUCache { head.next = node; node.next.prev = node; } - - private Node removeTail() { - Node node = tail.prev; - removeNode(node); - return node; - } } /** @@ -253,89 +237,75 @@ class LRUCache { #### C++ ```cpp -struct Node { - int k; - int v; - Node* prev; - Node* next; - - Node() - : k(0) - , v(0) - , prev(nullptr) - , next(nullptr) {} - Node(int key, int val) - : k(key) - , v(val) - , prev(nullptr) - , next(nullptr) {} -}; - class LRUCache { +private: + struct Node { + int key, val; + Node* prev; + Node* next; + Node(int key, int val) + : key(key) + , val(val) + , prev(nullptr) + , next(nullptr) {} + }; + + int size; + int capacity; + Node* head; + Node* tail; + unordered_map cache; + + void removeNode(Node* node) { + node->prev->next = node->next; + node->next->prev = node->prev; + } + + void addToHead(Node* node) { + node->next = head->next; + node->prev = head; + head->next->prev = node; + head->next = node; + } + public: LRUCache(int capacity) - : cap(capacity) - , size(0) { - head = new Node(); - tail = new Node(); + : size(0) + , capacity(capacity) { + head = new Node(0, 0); + tail = new Node(0, 0); head->next = tail; tail->prev = head; } int get(int key) { - if (!cache.count(key)) return -1; + if (!cache.contains(key)) { + return -1; + } Node* node = cache[key]; - moveToHead(node); - return node->v; + removeNode(node); + addToHead(node); + return node->val; } void put(int key, int value) { - if (cache.count(key)) { + if (cache.contains(key)) { Node* node = cache[key]; - node->v = value; - moveToHead(node); + removeNode(node); + node->val = value; + addToHead(node); } else { Node* node = new Node(key, value); cache[key] = node; addToHead(node); - ++size; - if (size > cap) { - node = removeTail(); - cache.erase(node->k); + if (++size > capacity) { + node = tail->prev; + cache.erase(node->key); + removeNode(node); --size; } } } - -private: - unordered_map cache; - Node* head; - Node* tail; - int cap; - int size; - - void moveToHead(Node* node) { - removeNode(node); - addToHead(node); - } - - void removeNode(Node* node) { - node->prev->next = node->next; - node->next->prev = node->prev; - } - - void addToHead(Node* node) { - node->next = head->next; - node->prev = head; - head->next = node; - node->next->prev = node; - } - - Node* removeTail() { - Node* node = tail->prev; - removeNode(node); - return node; - } }; /** @@ -349,104 +319,159 @@ private: #### Go ```go -type node struct { +type Node struct { key, val int - prev, next *node + prev, next *Node } type LRUCache struct { - capacity int - cache map[int]*node - head, tail *node + size, capacity int + head, tail *Node + cache map[int]*Node } func Constructor(capacity int) LRUCache { - head := new(node) - tail := new(node) + head := &Node{} + tail := &Node{} head.next = tail tail.prev = head return LRUCache{ capacity: capacity, - cache: make(map[int]*node, capacity), head: head, tail: tail, + cache: make(map[int]*Node), } } func (this *LRUCache) Get(key int) int { - n, ok := this.cache[key] - if !ok { - return -1 + if node, exists := this.cache[key]; exists { + this.removeNode(node) + this.addToHead(node) + return node.val } - this.moveToFront(n) - return n.val + return -1 } func (this *LRUCache) Put(key int, value int) { - n, ok := this.cache[key] - if ok { - n.val = value - this.moveToFront(n) - return - } - if len(this.cache) == this.capacity { - back := this.tail.prev - this.remove(back) - delete(this.cache, back.key) + if node, exists := this.cache[key]; exists { + this.removeNode(node) + node.val = value + this.addToHead(node) + } else { + node := &Node{key: key, val: value} + this.cache[key] = node + this.addToHead(node) + if this.size++; this.size > this.capacity { + node = this.tail.prev + delete(this.cache, node.key) + this.removeNode(node) + this.size-- + } } - n = &node{key: key, val: value} - this.pushFront(n) - this.cache[key] = n } -func (this *LRUCache) moveToFront(n *node) { - this.remove(n) - this.pushFront(n) +func (this *LRUCache) removeNode(node *Node) { + node.prev.next = node.next + node.next.prev = node.prev } -func (this *LRUCache) remove(n *node) { - n.prev.next = n.next - n.next.prev = n.prev - n.prev = nil - n.next = nil +func (this *LRUCache) addToHead(node *Node) { + node.next = this.head.next + node.prev = this.head + this.head.next = node + node.next.prev = node } -func (this *LRUCache) pushFront(n *node) { - n.prev = this.head - n.next = this.head.next - this.head.next.prev = n - this.head.next = n -} +/** + * Your LRUCache object will be instantiated and called as such: + * obj := Constructor(capacity); + * param_1 := obj.Get(key); + * obj.Put(key,value); + */ + +/** + * Your LRUCache object will be instantiated and called as such: + * obj := Constructor(capacity); + * param_1 := obj.Get(key); + * obj.Put(key,value); + */ ``` #### TypeScript ```ts +class Node { + key: number; + val: number; + prev: Node | null; + next: Node | null; + + constructor(key: number, val: number) { + this.key = key; + this.val = val; + this.prev = null; + this.next = null; + } +} + class LRUCache { - capacity: number; - map: Map; + private size: number; + private capacity: number; + private head: Node; + private tail: Node; + private cache: Map; + constructor(capacity: number) { + this.size = 0; this.capacity = capacity; - this.map = new Map(); + this.head = new Node(0, 0); + this.tail = new Node(0, 0); + this.head.next = this.tail; + this.tail.prev = this.head; + this.cache = new Map(); } get(key: number): number { - if (this.map.has(key)) { - const val = this.map.get(key)!; - this.map.delete(key); - this.map.set(key, val); - return val; + if (!this.cache.has(key)) { + return -1; } - return -1; + const node = this.cache.get(key)!; + this.removeNode(node); + this.addToHead(node); + return node.val; } put(key: number, value: number): void { - this.map.delete(key); - this.map.set(key, value); - if (this.map.size > this.capacity) { - this.map.delete(this.map.keys().next().value); + if (this.cache.has(key)) { + const node = this.cache.get(key)!; + this.removeNode(node); + node.val = value; + this.addToHead(node); + } else { + const node = new Node(key, value); + this.cache.set(key, node); + this.addToHead(node); + if (++this.size > this.capacity) { + const nodeToRemove = this.tail.prev!; + this.cache.delete(nodeToRemove.key); + this.removeNode(nodeToRemove); + --this.size; + } } } + + private removeNode(node: Node): void { + if (!node) return; + node.prev!.next = node.next; + node.next!.prev = node.prev; + } + + private addToHead(node: Node): void { + node.next = this.head.next; + node.prev = this.head; + this.head.next!.prev = node; + this.head.next = node; + } } /** @@ -585,22 +610,102 @@ impl LRUCache { } ``` +#### JavaScript + +```js +/** + * @param {number} capacity + */ +var LRUCache = function (capacity) { + this.size = 0; + this.capacity = capacity; + this.cache = new Map(); + this.head = new Node(0, 0); + this.tail = new Node(0, 0); + this.head.next = this.tail; + this.tail.prev = this.head; +}; + +/** + * @param {number} key + * @return {number} + */ +LRUCache.prototype.get = function (key) { + if (!this.cache.has(key)) { + return -1; + } + const node = this.cache.get(key); + this.removeNode(node); + this.addToHead(node); + return node.val; +}; + +/** + * @param {number} key + * @param {number} value + * @return {void} + */ +LRUCache.prototype.put = function (key, value) { + if (this.cache.has(key)) { + const node = this.cache.get(key); + this.removeNode(node); + node.val = value; + this.addToHead(node); + } else { + const node = new Node(key, value); + this.cache.set(key, node); + this.addToHead(node); + if (++this.size > this.capacity) { + const nodeToRemove = this.tail.prev; + this.cache.delete(nodeToRemove.key); + this.removeNode(nodeToRemove); + --this.size; + } + } +}; + +LRUCache.prototype.removeNode = function (node) { + if (!node) return; + node.prev.next = node.next; + node.next.prev = node.prev; +}; + +LRUCache.prototype.addToHead = function (node) { + node.next = this.head.next; + node.prev = this.head; + this.head.next.prev = node; + this.head.next = node; +}; + +/** + * @constructor + * @param {number} key + * @param {number} val + */ +function Node(key, val) { + this.key = key; + this.val = val; + this.prev = null; + this.next = null; +} + +/** + * Your LRUCache object will be instantiated and called as such: + * var obj = new LRUCache(capacity) + * var param_1 = obj.get(key) + * obj.put(key,value) + */ +``` + #### C# ```cs public class LRUCache { - class Node { - public Node Prev; - public Node Next; - public int Key; - public int Val; - } - + private int size; + private int capacity; + private Dictionary cache = new Dictionary(); private Node head = new Node(); private Node tail = new Node(); - private Dictionary cache = new Dictionary(); - private readonly int capacity; - private int size; public LRUCache(int capacity) { this.capacity = capacity; @@ -609,52 +714,59 @@ public class LRUCache { } public int Get(int key) { - Node node; - if (cache.TryGetValue(key, out node)) { - moveToHead(node); - return node.Val; + if (!cache.ContainsKey(key)) { + return -1; } - return -1; - } - - public void Put(int key, int Val) { - Node node; - if (cache.TryGetValue(key, out node)) { - moveToHead(node); - node.Val = Val; + Node node = cache[key]; + RemoveNode(node); + AddToHead(node); + return node.Val; + } + + public void Put(int key, int value) { + if (cache.ContainsKey(key)) { + Node node = cache[key]; + RemoveNode(node); + node.Val = value; + AddToHead(node); } else { - node = new Node() { Key = key, Val = Val }; - cache.Add(key, node); - addToHead(node); + Node node = new Node(key, value); + cache[key] = node; + AddToHead(node); if (++size > capacity) { - node = removeTail(); + node = tail.Prev; cache.Remove(node.Key); + RemoveNode(node); --size; } } } - private void moveToHead(Node node) { - removeNode(node); - addToHead(node); - } - - private void removeNode(Node node) { + private void RemoveNode(Node node) { node.Prev.Next = node.Next; node.Next.Prev = node.Prev; } - private void addToHead(Node node) { + private void AddToHead(Node node) { node.Next = head.Next; node.Prev = head; head.Next = node; node.Next.Prev = node; } - private Node removeTail() { - Node node = tail.Prev; - removeNode(node); - return node; + // Node class to represent each entry in the cache. + private class Node { + public int Key; + public int Val; + public Node Prev; + public Node Next; + + public Node() {} + + public Node(int key, int val) { + Key = key; + Val = val; + } } } @@ -662,7 +774,7 @@ public class LRUCache { * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.Get(key); - * obj.Put(key,Val); + * obj.Put(key,value); */ ``` diff --git a/solution/0100-0199/0146.LRU Cache/README_EN.md b/solution/0100-0199/0146.LRU Cache/README_EN.md index c3dbdaea5a858..722c06189a890 100644 --- a/solution/0100-0199/0146.LRU Cache/README_EN.md +++ b/solution/0100-0199/0146.LRU Cache/README_EN.md @@ -89,7 +89,7 @@ The time complexity is $O(1)$, and the space complexity is $O(\textit{capacity}) ```python class Node: - def __init__(self, key=0, val=0): + def __init__(self, key: int = 0, val: int = 0): self.key = key self.val = val self.prev = None @@ -97,12 +97,13 @@ class Node: class LRUCache: + def __init__(self, capacity: int): + self.size = 0 + self.capacity = capacity self.cache = {} self.head = Node() self.tail = Node() - self.capacity = capacity - self.size = 0 self.head.next = self.tail self.tail.prev = self.head @@ -110,28 +111,27 @@ class LRUCache: if key not in self.cache: return -1 node = self.cache[key] - self.move_to_head(node) + self.remove_node(node) + self.add_to_head(node) return node.val def put(self, key: int, value: int) -> None: if key in self.cache: node = self.cache[key] + self.remove_node(node) node.val = value - self.move_to_head(node) + self.add_to_head(node) else: node = Node(key, value) self.cache[key] = node self.add_to_head(node) self.size += 1 if self.size > self.capacity: - node = self.remove_tail() + node = self.tail.prev self.cache.pop(node.key) + self.remove_node(node) self.size -= 1 - def move_to_head(self, node): - self.remove_node(node) - self.add_to_head(node) - def remove_node(self, node): node.prev.next = node.next node.next.prev = node.prev @@ -142,11 +142,6 @@ class LRUCache: self.head.next = node node.next.prev = node - def remove_tail(self): - node = self.tail.prev - self.remove_node(node) - return node - # Your LRUCache object will be instantiated and called as such: # obj = LRUCache(capacity) @@ -158,10 +153,8 @@ class LRUCache: ```java class Node { - int key; - int val; - Node prev; - Node next; + int key, val; + Node prev, next; Node() { } @@ -173,11 +166,11 @@ class Node { } class LRUCache { - private Map cache = new HashMap<>(); + private int size; + private int capacity; private Node head = new Node(); private Node tail = new Node(); - private int capacity; - private int size; + private Map cache = new HashMap<>(); public LRUCache(int capacity) { this.capacity = capacity; @@ -190,33 +183,30 @@ class LRUCache { return -1; } Node node = cache.get(key); - moveToHead(node); + removeNode(node); + addToHead(node); return node.val; } public void put(int key, int value) { if (cache.containsKey(key)) { Node node = cache.get(key); + removeNode(node); node.val = value; - moveToHead(node); + addToHead(node); } else { Node node = new Node(key, value); cache.put(key, node); addToHead(node); - ++size; - if (size > capacity) { - node = removeTail(); + if (++size > capacity) { + node = tail.prev; cache.remove(node.key); + removeNode(node); --size; } } } - private void moveToHead(Node node) { - removeNode(node); - addToHead(node); - } - private void removeNode(Node node) { node.prev.next = node.next; node.next.prev = node.prev; @@ -228,12 +218,6 @@ class LRUCache { head.next = node; node.next.prev = node; } - - private Node removeTail() { - Node node = tail.prev; - removeNode(node); - return node; - } } /** @@ -247,89 +231,75 @@ class LRUCache { #### C++ ```cpp -struct Node { - int k; - int v; - Node* prev; - Node* next; - - Node() - : k(0) - , v(0) - , prev(nullptr) - , next(nullptr) {} - Node(int key, int val) - : k(key) - , v(val) - , prev(nullptr) - , next(nullptr) {} -}; - class LRUCache { +private: + struct Node { + int key, val; + Node* prev; + Node* next; + Node(int key, int val) + : key(key) + , val(val) + , prev(nullptr) + , next(nullptr) {} + }; + + int size; + int capacity; + Node* head; + Node* tail; + unordered_map cache; + + void removeNode(Node* node) { + node->prev->next = node->next; + node->next->prev = node->prev; + } + + void addToHead(Node* node) { + node->next = head->next; + node->prev = head; + head->next->prev = node; + head->next = node; + } + public: LRUCache(int capacity) - : cap(capacity) - , size(0) { - head = new Node(); - tail = new Node(); + : size(0) + , capacity(capacity) { + head = new Node(0, 0); + tail = new Node(0, 0); head->next = tail; tail->prev = head; } int get(int key) { - if (!cache.count(key)) return -1; + if (!cache.contains(key)) { + return -1; + } Node* node = cache[key]; - moveToHead(node); - return node->v; + removeNode(node); + addToHead(node); + return node->val; } void put(int key, int value) { - if (cache.count(key)) { + if (cache.contains(key)) { Node* node = cache[key]; - node->v = value; - moveToHead(node); + removeNode(node); + node->val = value; + addToHead(node); } else { Node* node = new Node(key, value); cache[key] = node; addToHead(node); - ++size; - if (size > cap) { - node = removeTail(); - cache.erase(node->k); + if (++size > capacity) { + node = tail->prev; + cache.erase(node->key); + removeNode(node); --size; } } } - -private: - unordered_map cache; - Node* head; - Node* tail; - int cap; - int size; - - void moveToHead(Node* node) { - removeNode(node); - addToHead(node); - } - - void removeNode(Node* node) { - node->prev->next = node->next; - node->next->prev = node->prev; - } - - void addToHead(Node* node) { - node->next = head->next; - node->prev = head; - head->next = node; - node->next->prev = node; - } - - Node* removeTail() { - Node* node = tail->prev; - removeNode(node); - return node; - } }; /** @@ -343,104 +313,159 @@ private: #### Go ```go -type node struct { +type Node struct { key, val int - prev, next *node + prev, next *Node } type LRUCache struct { - capacity int - cache map[int]*node - head, tail *node + size, capacity int + head, tail *Node + cache map[int]*Node } func Constructor(capacity int) LRUCache { - head := new(node) - tail := new(node) + head := &Node{} + tail := &Node{} head.next = tail tail.prev = head return LRUCache{ capacity: capacity, - cache: make(map[int]*node, capacity), head: head, tail: tail, + cache: make(map[int]*Node), } } func (this *LRUCache) Get(key int) int { - n, ok := this.cache[key] - if !ok { - return -1 + if node, exists := this.cache[key]; exists { + this.removeNode(node) + this.addToHead(node) + return node.val } - this.moveToFront(n) - return n.val + return -1 } func (this *LRUCache) Put(key int, value int) { - n, ok := this.cache[key] - if ok { - n.val = value - this.moveToFront(n) - return - } - if len(this.cache) == this.capacity { - back := this.tail.prev - this.remove(back) - delete(this.cache, back.key) + if node, exists := this.cache[key]; exists { + this.removeNode(node) + node.val = value + this.addToHead(node) + } else { + node := &Node{key: key, val: value} + this.cache[key] = node + this.addToHead(node) + if this.size++; this.size > this.capacity { + node = this.tail.prev + delete(this.cache, node.key) + this.removeNode(node) + this.size-- + } } - n = &node{key: key, val: value} - this.pushFront(n) - this.cache[key] = n } -func (this *LRUCache) moveToFront(n *node) { - this.remove(n) - this.pushFront(n) +func (this *LRUCache) removeNode(node *Node) { + node.prev.next = node.next + node.next.prev = node.prev } -func (this *LRUCache) remove(n *node) { - n.prev.next = n.next - n.next.prev = n.prev - n.prev = nil - n.next = nil +func (this *LRUCache) addToHead(node *Node) { + node.next = this.head.next + node.prev = this.head + this.head.next = node + node.next.prev = node } -func (this *LRUCache) pushFront(n *node) { - n.prev = this.head - n.next = this.head.next - this.head.next.prev = n - this.head.next = n -} +/** + * Your LRUCache object will be instantiated and called as such: + * obj := Constructor(capacity); + * param_1 := obj.Get(key); + * obj.Put(key,value); + */ + +/** + * Your LRUCache object will be instantiated and called as such: + * obj := Constructor(capacity); + * param_1 := obj.Get(key); + * obj.Put(key,value); + */ ``` #### TypeScript ```ts +class Node { + key: number; + val: number; + prev: Node | null; + next: Node | null; + + constructor(key: number, val: number) { + this.key = key; + this.val = val; + this.prev = null; + this.next = null; + } +} + class LRUCache { - capacity: number; - map: Map; + private size: number; + private capacity: number; + private head: Node; + private tail: Node; + private cache: Map; + constructor(capacity: number) { + this.size = 0; this.capacity = capacity; - this.map = new Map(); + this.head = new Node(0, 0); + this.tail = new Node(0, 0); + this.head.next = this.tail; + this.tail.prev = this.head; + this.cache = new Map(); } get(key: number): number { - if (this.map.has(key)) { - const val = this.map.get(key)!; - this.map.delete(key); - this.map.set(key, val); - return val; + if (!this.cache.has(key)) { + return -1; } - return -1; + const node = this.cache.get(key)!; + this.removeNode(node); + this.addToHead(node); + return node.val; } put(key: number, value: number): void { - this.map.delete(key); - this.map.set(key, value); - if (this.map.size > this.capacity) { - this.map.delete(this.map.keys().next().value); + if (this.cache.has(key)) { + const node = this.cache.get(key)!; + this.removeNode(node); + node.val = value; + this.addToHead(node); + } else { + const node = new Node(key, value); + this.cache.set(key, node); + this.addToHead(node); + if (++this.size > this.capacity) { + const nodeToRemove = this.tail.prev!; + this.cache.delete(nodeToRemove.key); + this.removeNode(nodeToRemove); + --this.size; + } } } + + private removeNode(node: Node): void { + if (!node) return; + node.prev!.next = node.next; + node.next!.prev = node.prev; + } + + private addToHead(node: Node): void { + node.next = this.head.next; + node.prev = this.head; + this.head.next!.prev = node; + this.head.next = node; + } } /** @@ -579,22 +604,102 @@ impl LRUCache { } ``` +#### JavaScript + +```js +/** + * @param {number} capacity + */ +var LRUCache = function (capacity) { + this.size = 0; + this.capacity = capacity; + this.cache = new Map(); + this.head = new Node(0, 0); + this.tail = new Node(0, 0); + this.head.next = this.tail; + this.tail.prev = this.head; +}; + +/** + * @param {number} key + * @return {number} + */ +LRUCache.prototype.get = function (key) { + if (!this.cache.has(key)) { + return -1; + } + const node = this.cache.get(key); + this.removeNode(node); + this.addToHead(node); + return node.val; +}; + +/** + * @param {number} key + * @param {number} value + * @return {void} + */ +LRUCache.prototype.put = function (key, value) { + if (this.cache.has(key)) { + const node = this.cache.get(key); + this.removeNode(node); + node.val = value; + this.addToHead(node); + } else { + const node = new Node(key, value); + this.cache.set(key, node); + this.addToHead(node); + if (++this.size > this.capacity) { + const nodeToRemove = this.tail.prev; + this.cache.delete(nodeToRemove.key); + this.removeNode(nodeToRemove); + --this.size; + } + } +}; + +LRUCache.prototype.removeNode = function (node) { + if (!node) return; + node.prev.next = node.next; + node.next.prev = node.prev; +}; + +LRUCache.prototype.addToHead = function (node) { + node.next = this.head.next; + node.prev = this.head; + this.head.next.prev = node; + this.head.next = node; +}; + +/** + * @constructor + * @param {number} key + * @param {number} val + */ +function Node(key, val) { + this.key = key; + this.val = val; + this.prev = null; + this.next = null; +} + +/** + * Your LRUCache object will be instantiated and called as such: + * var obj = new LRUCache(capacity) + * var param_1 = obj.get(key) + * obj.put(key,value) + */ +``` + #### C# ```cs public class LRUCache { - class Node { - public Node Prev; - public Node Next; - public int Key; - public int Val; - } - + private int size; + private int capacity; + private Dictionary cache = new Dictionary(); private Node head = new Node(); private Node tail = new Node(); - private Dictionary cache = new Dictionary(); - private readonly int capacity; - private int size; public LRUCache(int capacity) { this.capacity = capacity; @@ -603,52 +708,59 @@ public class LRUCache { } public int Get(int key) { - Node node; - if (cache.TryGetValue(key, out node)) { - moveToHead(node); - return node.Val; + if (!cache.ContainsKey(key)) { + return -1; } - return -1; - } - - public void Put(int key, int Val) { - Node node; - if (cache.TryGetValue(key, out node)) { - moveToHead(node); - node.Val = Val; + Node node = cache[key]; + RemoveNode(node); + AddToHead(node); + return node.Val; + } + + public void Put(int key, int value) { + if (cache.ContainsKey(key)) { + Node node = cache[key]; + RemoveNode(node); + node.Val = value; + AddToHead(node); } else { - node = new Node() { Key = key, Val = Val }; - cache.Add(key, node); - addToHead(node); + Node node = new Node(key, value); + cache[key] = node; + AddToHead(node); if (++size > capacity) { - node = removeTail(); + node = tail.Prev; cache.Remove(node.Key); + RemoveNode(node); --size; } } } - private void moveToHead(Node node) { - removeNode(node); - addToHead(node); - } - - private void removeNode(Node node) { + private void RemoveNode(Node node) { node.Prev.Next = node.Next; node.Next.Prev = node.Prev; } - private void addToHead(Node node) { + private void AddToHead(Node node) { node.Next = head.Next; node.Prev = head; head.Next = node; node.Next.Prev = node; } - private Node removeTail() { - Node node = tail.Prev; - removeNode(node); - return node; + // Node class to represent each entry in the cache. + private class Node { + public int Key; + public int Val; + public Node Prev; + public Node Next; + + public Node() {} + + public Node(int key, int val) { + Key = key; + Val = val; + } } } @@ -656,7 +768,7 @@ public class LRUCache { * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.Get(key); - * obj.Put(key,Val); + * obj.Put(key,value); */ ``` diff --git a/solution/0100-0199/0146.LRU Cache/Solution.cpp b/solution/0100-0199/0146.LRU Cache/Solution.cpp index 2c467d2c13297..14bb151c83f8a 100644 --- a/solution/0100-0199/0146.LRU Cache/Solution.cpp +++ b/solution/0100-0199/0146.LRU Cache/Solution.cpp @@ -1,86 +1,72 @@ -struct Node { - int k; - int v; - Node* prev; - Node* next; +class LRUCache { +private: + struct Node { + int key, val; + Node* prev; + Node* next; + Node(int key, int val) + : key(key) + , val(val) + , prev(nullptr) + , next(nullptr) {} + }; - Node() - : k(0) - , v(0) - , prev(nullptr) - , next(nullptr) {} - Node(int key, int val) - : k(key) - , v(val) - , prev(nullptr) - , next(nullptr) {} -}; + int size; + int capacity; + Node* head; + Node* tail; + unordered_map cache; + + void removeNode(Node* node) { + node->prev->next = node->next; + node->next->prev = node->prev; + } + + void addToHead(Node* node) { + node->next = head->next; + node->prev = head; + head->next->prev = node; + head->next = node; + } -class LRUCache { public: LRUCache(int capacity) - : cap(capacity) - , size(0) { - head = new Node(); - tail = new Node(); + : size(0) + , capacity(capacity) { + head = new Node(0, 0); + tail = new Node(0, 0); head->next = tail; tail->prev = head; } int get(int key) { - if (!cache.count(key)) return -1; + if (!cache.contains(key)) { + return -1; + } Node* node = cache[key]; - moveToHead(node); - return node->v; + removeNode(node); + addToHead(node); + return node->val; } void put(int key, int value) { - if (cache.count(key)) { + if (cache.contains(key)) { Node* node = cache[key]; - node->v = value; - moveToHead(node); + removeNode(node); + node->val = value; + addToHead(node); } else { Node* node = new Node(key, value); cache[key] = node; addToHead(node); - ++size; - if (size > cap) { - node = removeTail(); - cache.erase(node->k); + if (++size > capacity) { + node = tail->prev; + cache.erase(node->key); + removeNode(node); --size; } } } - -private: - unordered_map cache; - Node* head; - Node* tail; - int cap; - int size; - - void moveToHead(Node* node) { - removeNode(node); - addToHead(node); - } - - void removeNode(Node* node) { - node->prev->next = node->next; - node->next->prev = node->prev; - } - - void addToHead(Node* node) { - node->next = head->next; - node->prev = head; - head->next = node; - node->next->prev = node; - } - - Node* removeTail() { - Node* node = tail->prev; - removeNode(node); - return node; - } }; /** @@ -88,4 +74,4 @@ class LRUCache { * LRUCache* obj = new LRUCache(capacity); * int param_1 = obj->get(key); * obj->put(key,value); - */ \ No newline at end of file + */ diff --git a/solution/0100-0199/0146.LRU Cache/Solution.cs b/solution/0100-0199/0146.LRU Cache/Solution.cs index a43d2901155ce..1ab6964ff372b 100644 --- a/solution/0100-0199/0146.LRU Cache/Solution.cs +++ b/solution/0100-0199/0146.LRU Cache/Solution.cs @@ -1,16 +1,9 @@ public class LRUCache { - class Node { - public Node Prev; - public Node Next; - public int Key; - public int Val; - } - + private int size; + private int capacity; + private Dictionary cache = new Dictionary(); private Node head = new Node(); private Node tail = new Node(); - private Dictionary cache = new Dictionary(); - private readonly int capacity; - private int size; public LRUCache(int capacity) { this.capacity = capacity; @@ -19,52 +12,59 @@ public LRUCache(int capacity) { } public int Get(int key) { - Node node; - if (cache.TryGetValue(key, out node)) { - moveToHead(node); - return node.Val; + if (!cache.ContainsKey(key)) { + return -1; } - return -1; + Node node = cache[key]; + RemoveNode(node); + AddToHead(node); + return node.Val; } - public void Put(int key, int Val) { - Node node; - if (cache.TryGetValue(key, out node)) { - moveToHead(node); - node.Val = Val; + public void Put(int key, int value) { + if (cache.ContainsKey(key)) { + Node node = cache[key]; + RemoveNode(node); + node.Val = value; + AddToHead(node); } else { - node = new Node() { Key = key, Val = Val }; - cache.Add(key, node); - addToHead(node); + Node node = new Node(key, value); + cache[key] = node; + AddToHead(node); if (++size > capacity) { - node = removeTail(); + node = tail.Prev; cache.Remove(node.Key); + RemoveNode(node); --size; } } } - private void moveToHead(Node node) { - removeNode(node); - addToHead(node); - } - - private void removeNode(Node node) { + private void RemoveNode(Node node) { node.Prev.Next = node.Next; node.Next.Prev = node.Prev; } - private void addToHead(Node node) { + private void AddToHead(Node node) { node.Next = head.Next; node.Prev = head; head.Next = node; node.Next.Prev = node; } - private Node removeTail() { - Node node = tail.Prev; - removeNode(node); - return node; + // Node class to represent each entry in the cache. + private class Node { + public int Key; + public int Val; + public Node Prev; + public Node Next; + + public Node() {} + + public Node(int key, int val) { + Key = key; + Val = val; + } } } @@ -72,5 +72,5 @@ private Node removeTail() { * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.Get(key); - * obj.Put(key,Val); + * obj.Put(key,value); */ diff --git a/solution/0100-0199/0146.LRU Cache/Solution.go b/solution/0100-0199/0146.LRU Cache/Solution.go index 0cdf1d342958f..cd4e012971341 100644 --- a/solution/0100-0199/0146.LRU Cache/Solution.go +++ b/solution/0100-0199/0146.LRU Cache/Solution.go @@ -1,68 +1,76 @@ -type node struct { +type Node struct { key, val int - prev, next *node + prev, next *Node } type LRUCache struct { - capacity int - cache map[int]*node - head, tail *node + size, capacity int + head, tail *Node + cache map[int]*Node } func Constructor(capacity int) LRUCache { - head := new(node) - tail := new(node) + head := &Node{} + tail := &Node{} head.next = tail tail.prev = head return LRUCache{ capacity: capacity, - cache: make(map[int]*node, capacity), head: head, tail: tail, + cache: make(map[int]*Node), } } func (this *LRUCache) Get(key int) int { - n, ok := this.cache[key] - if !ok { - return -1 + if node, exists := this.cache[key]; exists { + this.removeNode(node) + this.addToHead(node) + return node.val } - this.moveToFront(n) - return n.val + return -1 } func (this *LRUCache) Put(key int, value int) { - n, ok := this.cache[key] - if ok { - n.val = value - this.moveToFront(n) - return + if node, exists := this.cache[key]; exists { + this.removeNode(node) + node.val = value + this.addToHead(node) + } else { + node := &Node{key: key, val: value} + this.cache[key] = node + this.addToHead(node) + if this.size++; this.size > this.capacity { + node = this.tail.prev + delete(this.cache, node.key) + this.removeNode(node) + this.size-- + } } - if len(this.cache) == this.capacity { - back := this.tail.prev - this.remove(back) - delete(this.cache, back.key) - } - n = &node{key: key, val: value} - this.pushFront(n) - this.cache[key] = n } -func (this *LRUCache) moveToFront(n *node) { - this.remove(n) - this.pushFront(n) +func (this *LRUCache) removeNode(node *Node) { + node.prev.next = node.next + node.next.prev = node.prev } -func (this *LRUCache) remove(n *node) { - n.prev.next = n.next - n.next.prev = n.prev - n.prev = nil - n.next = nil +func (this *LRUCache) addToHead(node *Node) { + node.next = this.head.next + node.prev = this.head + this.head.next = node + node.next.prev = node } -func (this *LRUCache) pushFront(n *node) { - n.prev = this.head - n.next = this.head.next - this.head.next.prev = n - this.head.next = n -} \ No newline at end of file +/** + * Your LRUCache object will be instantiated and called as such: + * obj := Constructor(capacity); + * param_1 := obj.Get(key); + * obj.Put(key,value); + */ + +/** + * Your LRUCache object will be instantiated and called as such: + * obj := Constructor(capacity); + * param_1 := obj.Get(key); + * obj.Put(key,value); + */ diff --git a/solution/0100-0199/0146.LRU Cache/Solution.java b/solution/0100-0199/0146.LRU Cache/Solution.java index 3cbf7a5105dd3..a6fa66f005edf 100644 --- a/solution/0100-0199/0146.LRU Cache/Solution.java +++ b/solution/0100-0199/0146.LRU Cache/Solution.java @@ -1,8 +1,6 @@ class Node { - int key; - int val; - Node prev; - Node next; + int key, val; + Node prev, next; Node() { } @@ -14,11 +12,11 @@ class Node { } class LRUCache { - private Map cache = new HashMap<>(); + private int size; + private int capacity; private Node head = new Node(); private Node tail = new Node(); - private int capacity; - private int size; + private Map cache = new HashMap<>(); public LRUCache(int capacity) { this.capacity = capacity; @@ -31,33 +29,30 @@ public int get(int key) { return -1; } Node node = cache.get(key); - moveToHead(node); + removeNode(node); + addToHead(node); return node.val; } public void put(int key, int value) { if (cache.containsKey(key)) { Node node = cache.get(key); + removeNode(node); node.val = value; - moveToHead(node); + addToHead(node); } else { Node node = new Node(key, value); cache.put(key, node); addToHead(node); - ++size; - if (size > capacity) { - node = removeTail(); + if (++size > capacity) { + node = tail.prev; cache.remove(node.key); + removeNode(node); --size; } } } - private void moveToHead(Node node) { - removeNode(node); - addToHead(node); - } - private void removeNode(Node node) { node.prev.next = node.next; node.next.prev = node.prev; @@ -69,12 +64,6 @@ private void addToHead(Node node) { head.next = node; node.next.prev = node; } - - private Node removeTail() { - Node node = tail.prev; - removeNode(node); - return node; - } } /** @@ -82,4 +71,4 @@ private Node removeTail() { * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); - */ \ No newline at end of file + */ diff --git a/solution/0100-0199/0146.LRU Cache/Solution.js b/solution/0100-0199/0146.LRU Cache/Solution.js new file mode 100644 index 0000000000000..e634430bfd42c --- /dev/null +++ b/solution/0100-0199/0146.LRU Cache/Solution.js @@ -0,0 +1,82 @@ +/** + * @param {number} capacity + */ +var LRUCache = function (capacity) { + this.size = 0; + this.capacity = capacity; + this.cache = new Map(); + this.head = new Node(0, 0); + this.tail = new Node(0, 0); + this.head.next = this.tail; + this.tail.prev = this.head; +}; + +/** + * @param {number} key + * @return {number} + */ +LRUCache.prototype.get = function (key) { + if (!this.cache.has(key)) { + return -1; + } + const node = this.cache.get(key); + this.removeNode(node); + this.addToHead(node); + return node.val; +}; + +/** + * @param {number} key + * @param {number} value + * @return {void} + */ +LRUCache.prototype.put = function (key, value) { + if (this.cache.has(key)) { + const node = this.cache.get(key); + this.removeNode(node); + node.val = value; + this.addToHead(node); + } else { + const node = new Node(key, value); + this.cache.set(key, node); + this.addToHead(node); + if (++this.size > this.capacity) { + const nodeToRemove = this.tail.prev; + this.cache.delete(nodeToRemove.key); + this.removeNode(nodeToRemove); + --this.size; + } + } +}; + +LRUCache.prototype.removeNode = function (node) { + if (!node) return; + node.prev.next = node.next; + node.next.prev = node.prev; +}; + +LRUCache.prototype.addToHead = function (node) { + node.next = this.head.next; + node.prev = this.head; + this.head.next.prev = node; + this.head.next = node; +}; + +/** + * @constructor + * @param {number} key + * @param {number} val + */ +function Node(key, val) { + this.key = key; + this.val = val; + this.prev = null; + this.next = null; +} + +/** + * Your LRUCache object will be instantiated and called as such: + * var obj = new LRUCache(capacity) + * var param_1 = obj.get(key) + * obj.put(key,value) + */ diff --git a/solution/0100-0199/0146.LRU Cache/Solution.py b/solution/0100-0199/0146.LRU Cache/Solution.py index 76457b08d8cfd..5faf6a82fa9de 100644 --- a/solution/0100-0199/0146.LRU Cache/Solution.py +++ b/solution/0100-0199/0146.LRU Cache/Solution.py @@ -1,5 +1,5 @@ class Node: - def __init__(self, key=0, val=0): + def __init__(self, key: int = 0, val: int = 0): self.key = key self.val = val self.prev = None @@ -8,11 +8,11 @@ def __init__(self, key=0, val=0): class LRUCache: def __init__(self, capacity: int): + self.size = 0 + self.capacity = capacity self.cache = {} self.head = Node() self.tail = Node() - self.capacity = capacity - self.size = 0 self.head.next = self.tail self.tail.prev = self.head @@ -20,28 +20,27 @@ def get(self, key: int) -> int: if key not in self.cache: return -1 node = self.cache[key] - self.move_to_head(node) + self.remove_node(node) + self.add_to_head(node) return node.val def put(self, key: int, value: int) -> None: if key in self.cache: node = self.cache[key] + self.remove_node(node) node.val = value - self.move_to_head(node) + self.add_to_head(node) else: node = Node(key, value) self.cache[key] = node self.add_to_head(node) self.size += 1 if self.size > self.capacity: - node = self.remove_tail() + node = self.tail.prev self.cache.pop(node.key) + self.remove_node(node) self.size -= 1 - def move_to_head(self, node): - self.remove_node(node) - self.add_to_head(node) - def remove_node(self, node): node.prev.next = node.next node.next.prev = node.prev @@ -52,11 +51,6 @@ def add_to_head(self, node): self.head.next = node node.next.prev = node - def remove_tail(self): - node = self.tail.prev - self.remove_node(node) - return node - # Your LRUCache object will be instantiated and called as such: # obj = LRUCache(capacity) diff --git a/solution/0100-0199/0146.LRU Cache/Solution.ts b/solution/0100-0199/0146.LRU Cache/Solution.ts index d297dec3c3e04..109e8d1bf26f0 100644 --- a/solution/0100-0199/0146.LRU Cache/Solution.ts +++ b/solution/0100-0199/0146.LRU Cache/Solution.ts @@ -1,28 +1,75 @@ +class Node { + key: number; + val: number; + prev: Node | null; + next: Node | null; + + constructor(key: number, val: number) { + this.key = key; + this.val = val; + this.prev = null; + this.next = null; + } +} + class LRUCache { - capacity: number; - map: Map; + private size: number; + private capacity: number; + private head: Node; + private tail: Node; + private cache: Map; + constructor(capacity: number) { + this.size = 0; this.capacity = capacity; - this.map = new Map(); + this.head = new Node(0, 0); + this.tail = new Node(0, 0); + this.head.next = this.tail; + this.tail.prev = this.head; + this.cache = new Map(); } get(key: number): number { - if (this.map.has(key)) { - const val = this.map.get(key)!; - this.map.delete(key); - this.map.set(key, val); - return val; + if (!this.cache.has(key)) { + return -1; } - return -1; + const node = this.cache.get(key)!; + this.removeNode(node); + this.addToHead(node); + return node.val; } put(key: number, value: number): void { - this.map.delete(key); - this.map.set(key, value); - if (this.map.size > this.capacity) { - this.map.delete(this.map.keys().next().value); + if (this.cache.has(key)) { + const node = this.cache.get(key)!; + this.removeNode(node); + node.val = value; + this.addToHead(node); + } else { + const node = new Node(key, value); + this.cache.set(key, node); + this.addToHead(node); + if (++this.size > this.capacity) { + const nodeToRemove = this.tail.prev!; + this.cache.delete(nodeToRemove.key); + this.removeNode(nodeToRemove); + --this.size; + } } } + + private removeNode(node: Node): void { + if (!node) return; + node.prev!.next = node.next; + node.next!.prev = node.prev; + } + + private addToHead(node: Node): void { + node.next = this.head.next; + node.prev = this.head; + this.head.next!.prev = node; + this.head.next = node; + } } /** diff --git a/solution/0600-0699/0649.Dota2 Senate/README_EN.md b/solution/0600-0699/0649.Dota2 Senate/README_EN.md index 41046b7247300..5dc05fbb76a9d 100644 --- a/solution/0600-0699/0649.Dota2 Senate/README_EN.md +++ b/solution/0600-0699/0649.Dota2 Senate/README_EN.md @@ -39,9 +39,9 @@ tags:
 Input: senate = "RD"
 Output: "Radiant"
-Explanation: 
-The first senator comes from Radiant and he can just ban the next senator's right in round 1. 
-And the second senator can't exercise any rights anymore since his right has been banned. 
+Explanation:
+The first senator comes from Radiant and he can just ban the next senator's right in round 1.
+And the second senator can't exercise any rights anymore since his right has been banned.
 And in round 2, the first senator can just announce the victory since he is the only guy in the senate who can vote.
 
@@ -50,10 +50,10 @@ And in round 2, the first senator can just announce the victory since he is the
 Input: senate = "RDD"
 Output: "Dire"
-Explanation: 
-The first senator comes from Radiant and he can just ban the next senator's right in round 1. 
-And the second senator can't exercise any rights anymore since his right has been banned. 
-And the third senator comes from Dire and he can ban the first senator's right in round 1. 
+Explanation:
+The first senator comes from Radiant and he can just ban the next senator's right in round 1.
+And the second senator can't exercise any rights anymore since his right has been banned.
+And the third senator comes from Dire and he can ban the first senator's right in round 1.
 And in round 2, the third senator can just announce the victory since he is the only guy in the senate who can vote.
 
@@ -72,7 +72,16 @@ And in round 2, the third senator can just announce the victory since he is the -### Solution 1 +### Solution 1: Queue + Simulation + +We create two queues $qr$ and $qd$ to record the indices of the Radiant and Dire senators, respectively. Then we start the simulation, where in each round we dequeue one senator from each queue and perform different operations based on their factions: + +- If the Radiant senator's index is less than the Dire senator's index, the Radiant senator can permanently ban the voting rights of the Dire senator. We add $n$ to the Radiant senator's index and enqueue it back to the end of the queue, indicating that this senator will participate in the next round of voting. +- If the Dire senator's index is less than the Radiant senator's index, the Dire senator can permanently ban the voting rights of the Radiant senator. We add $n$ to the Dire senator's index and enqueue it back to the end of the queue, indicating that this senator will participate in the next round of voting. + +Finally, when there are only senators from one faction left in the queues, the senators from that faction win. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of senators.