Problem k个一组翻转链表https://leetcode.cn/problems/reverse-nodes-in-k-group/submissions/540674966/?envType=study-plan-v2&envId=top-100-liked
Solution 引入dummy节点避免对头节点的特殊处理, pre->cur->next1->next2->next[k-1]->next => pre->next[k-1]->next2->next1->cur->next 通过pre找到cur和next节点,然后反转cur->next[k-1]链表并将反转后的链表连接到pre后面和next前面,更新pre指针,遍历整个链表 在pre为空或者剩余链表长度小于K时结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 class Solution {public : ListNode *reverse (ListNode *end, ListNode *start) { ListNode *p = start; ListNode *pre = end; while (p != end) { ListNode *next = p->next; p->next = pre; pre = p; p = next; } return pre; } ListNode* reverseKGroup (ListNode* head, int k) { ListNode dummy (0 , head) ; ListNode *pre = &dummy; while (pre) { ListNode *cur = pre->next; ListNode *next = cur; int i = 0 ; for (; i < k; i ++) { if (next == nullptr ) break ; next = next->next; } if (i != k) break ; pre->next = reverse (next, cur); pre = cur; } return dummy.next; } };
Problem 随机链表的复制https://leetcode.cn/problems/copy-list-with-random-pointer/description/?envType=study-plan-v2&envId=top-100-liked
Solution 第一次遍历列表,忽略random指针,拷贝链表并使用map建立老节点和新节点对应关系,第二次遍历列表根据老节点新节点对应关系 初始化新链表的random域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class Solution {public : Node* copyRandomList (Node* head) { unordered_map<Node *, Node *> old2new; Node *ret = nullptr ; Node dummy (0 , nullptr ) ; Node *p_new = dummy.next; Node *pre = &dummy; Node *p = head; while (p) { pre->next = new Node (p->val); old2new[p] = pre->next; pre = pre->next; p = p->next; } p = head; p_new = dummy.next; while (p) { if (p->random) p_new->random = old2new[p->random]; p = p->next; p_new = p_new->next; } return dummy.next; } };
Problem 排序链表https://leetcode.cn/problems/sort-list/description/?envType=study-plan-v2&envId=top-100-liked
Solution 总体采用合并两个有序链表的思路来做,每次遍历列表,合并相邻两个已排序链表,合并长度由1到len/2 + 1,刚开始合并相邻两个长度为1的链表,下一次合并相邻两个长度为2的链表,以此类推,每次需要找到需要合并的两个链表的头和尾,将尾指针next置空然后合并两个列表,将合并后的链表接到pre_tail后面,更新指针有一些细节要注意,详见代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 class Solution {public : ListNode *merge2SortedList (ListNode *head1, ListNode *head2) { ListNode dummy (0 , nullptr ) ; ListNode *p = &dummy; ListNode *p1 = head1, *p2 = head2; while (p1 && p2) { if (p1->val < p2->val) { p->next = p1; p1 = p1->next; } else { p->next = p2; p2 = p2->next; } p = p->next; } p->next = p1 ? p1 : p2; return dummy.next; } ListNode* sortList (ListNode* head) { int list_len = 0 ; ListNode *p = head; while (p) { list_len ++; p = p->next; } ListNode dummy (0 , head) ; for (int len = 1 ; len < list_len; len *= 2 ) { ListNode *cur = dummy.next; ListNode *pre_tail = &dummy; while (cur) { ListNode *tail1 = cur; ListNode *head2 = cur; for (int i = 0 ; i < len - 1 && tail1->next != nullptr ; i ++) { tail1 = tail1->next; } head2 = tail1->next; tail1->next = nullptr ; ListNode *tail2 = head2; for (int i = 0 ; i < len - 1 && tail2 && tail2->next != nullptr ; i ++) { tail2 = tail2->next; } ListNode *next_head = tail2 ? tail2->next : nullptr ; if (tail2) tail2->next = nullptr ; ListNode *merged = merge2SortedList (cur, head2); pre_tail->next = merged; if (tail1 && tail2) { pre_tail = tail1->val >= tail2->val ? tail1 : tail2; } else { pre_tail = tail1 ? tail1 : tail2; } cur = next_head; } } return dummy.next; } };
Problem 合并k个升序链表https://leetcode.cn/problems/merge-k-sorted-lists/?envType=study-plan-v2&envId=top-100-liked
Solution 分支,将k个升序链表分成两组,对这两组链表做k/2个升序链表的排序,合并两个排序后的链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class Solution {public : ListNode *merge2Lists (ListNode *head1, ListNode *head2) { ListNode dummy (0 , nullptr ) ; ListNode *p = &dummy, *p1 = head1, *p2 = head2; while (p1 && p2) { if (p1->val < p2->val) { p->next = p1; p1 = p1->next; } else { p->next = p2; p2 = p2->next; } p = p->next; } p->next = p1 ? p1 : p2; return dummy.next; } ListNode *mergeLists (vector<ListNode *> &lists, int l, int r) { if (l > r) return nullptr ; if (l == r) return lists[l]; int mid = (l + r) / 2 ; return merge2Lists (mergeLists (lists, l, mid), mergeLists (lists, mid+1 , r)); } ListNode* mergeKLists (vector<ListNode*>& lists) { return mergeLists (lists, 0 , lists.size ()-1 ); } };
Problem LRU 缓存https://leetcode.cn/problems/lru-cache/description/?envType=study-plan-v2&envId=top-100-liked
Solution map存储key-node用于查找,双向链表由于处理LRU的移动节点操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 class Node { public : int key, value; Node *pre, *next; Node (int key_, int val_) : key (key_), value (val_), pre (nullptr ), next (nullptr ) {} }; class LRUCache {public : unordered_map<int , Node *> cache; Node head; Node tail; int cap; void removeNode (Node *node) { Node *pre = node->pre; Node *next = node->next; pre->next = next; next->pre = pre; } void moveToHead (Node *node) { removeNode (node); node->next = head.next; head.next = node; node->pre = &head; node->next->pre = node; } void deleteTail () { Node *node = tail.pre; node->pre->next = &tail; tail.pre = node->pre; cache.erase (node->key); delete node; } LRUCache (int capacity): head (0 , 0 ), tail (0 , 0 ) { cap = capacity; head.next = &tail; tail.pre = &head; } int get (int key) { if (cache.count (key)) { Node *pnode = cache[key]; moveToHead (pnode); return pnode->value; } return -1 ; } void put (int key, int value) { if (cache.count (key)) { Node *pnode = cache[key]; moveToHead (pnode); pnode->value = value; } else { if (cache.size () == cap) { deleteTail (); } Node *pnode = new Node (key, value); pnode->next = head.next; pnode->pre = &head; head.next = pnode; pnode->next->pre = pnode; cache[key] = pnode; } } };