【道德经·第十二章】五色令人目盲,五音令人耳聋,五味令人口爽,驰骋畋(tián)猎令人心发狂,难得之货令人行妨。是以圣人为腹不为目,故去彼取此。
链表结构定义
1 2 3 4 5 6 7 8
| struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} };
|
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode *dummy = new ListNode(-1); dummy->next = head;
ListNode *fast = head, *slow = dummy; for(int i = 1; i <= n; i++) fast = fast->next; while(fast) { fast = fast->next; slow = slow->next; } ListNode *t = slow->next; slow->next= slow->next->next; delete t; return dummy->next; }
|
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
本题有两种解决思路,一种递归一种迭代,思路都很精巧,下面来一一介绍:
1、递归解法
1 2 3 4 5 6 7 8 9 10
| ListNode* reverseList(ListNode* head) { if(head==nullptr || head->next==nullptr) return head;
ListNode *newHead = reverseList(head->next); head->next->next = head; head->next = nullptr return newHead; }
|
2、迭代解法
1 2 3 4 5 6 7 8 9 10 11
| ListNode* reverseList(ListNode* head) { ListNode *pre = nullptr, *cur = head; while(cur) { LisNode *nxt = cur->next; cur->next = pre; pre = cur; cur = nxt; }
return pre; }
|
反转从位置left到位置right的链表节点。
1、递归解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| ListNode* reverseBetween(ListNode* head, int left, int right) { if(left == 1) { return reverseN(head, right); }
head->next = reverseBetween(head->next, left-1, right-1); return head; }
ListNode *successor = nullptr; ListNode* reverseN(ListNode* head, int n) { if(n == 1) { successor = head->next; return head; }
ListNode *newHead = reverseN(head->next, n-1); head->next->next = head; head->next = successor; return newHead; }
|
2、迭代解法(推荐)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ListNode* reverseBetween(ListNode* head, int left, int right) { ListNode *dummy = new ListNode(-1, head); ListNode *pre = dummy;
for(int i = 1; i <= left-1; i++) pre = pre->next; ListNode *cur = pre->next; for(int i = left; i < right; i++) { ListNode *t = cur->next; cur->next = t->next; t->next = pre->next; pre->next = t; }
return dummy->next; }
|
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ListNode* reverseKGroup(ListNode* head, int k) { ListNode *a = head, *b = head; for(int i = 0; i < k; i++) { if(b == nullptr) return a; b = b->next; }
ListNode *newHead = revList(a, b); a->next = reverseKGroup(b, k); return newHead; }
ListNode* revList(ListNode* a, ListNode* b) { ListNode *pre = nullptr, *cur = a; while(cur != b) { ListNode *nxt = cur->next; cur->next = pre; pre = cur; cur = nxt; }
return pre; }
|
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。
1、递归解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ListNode *left = nullptr; bool isPalindrome(ListNode* head) { left = head; return traverse(head); }
bool traverse(ListNode* right) { if(right == nullptr) { return true; } bool res = traverse(right->next); res = res && (left->val == right->val); left = left->next; return res; }
|
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
| bool isPalindrome(ListNode* head) { if(head==nullptr || head->next==nullptr) return true; ListNode *fast = head, *slow = head; while(fast->next && fast->next->next) { slow = slow->next; fast = fast->next->next; }
ListNode *right = slow->next, *left = head; slow->next = nullptr; right = revList(right); while(right != nullptr) { if(left->val != right->val) return false; left = left->next; right = right->next; } return true; }
ListNode* revList(ListNode* l) { ListNode *pre = nullptr, *cur = l; while(cur != nullptr) { ListNode* t = cur->next; cur->next = pre; pre = cur; cur = t; } return pre; }
|
将两个升序链表合并为一个新的 升序 链表并返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { ListNode *dummy = new ListNode(-1, nullptr); ListNode *cur = dummy;
while(list1 && list2) { if(list1->val < list2->val) { cur->next = list1; list1 = list1->next; } else { cur->next = list2; list2 = list2->next; }
cur = cur->next; }
if(list1) cur->next = list1; if(list2) cur->next = list2;
return dummy->next; }
|
给你一个链表的头节点 head ,判断链表中是否有环。
1 2 3 4 5 6 7 8 9 10 11
| bool hasCycle(ListNode *head) { ListNode *fast = head, *slow = head; while(fast && fast->next) { fast = fast->next->next; slow = slow->next;
if(fast == slow) return true; }
return false; }
|
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ListNode *detectCycle(ListNode *head) { ListNode *slow = head, *fast = head; while(fast && fast->next) { slow = slow->next; fast = fast->next->next; if(slow == fast) break; } if(!fast || !fast->next) return nullptr; slow = head; while(slow != fast) { slow = slow->next; fast = fast->next; } return slow; }
|
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
1 2 3 4 5 6 7 8 9 10 11
| ListNode* middleNode(ListNode* head) { ListNode *fast = head; ListNode *slow = head; while(fast && fast->next) { fast = fast->next->next; slow = slow->next; }
return slow; }
|
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。 如果两个链表不存在相交节点,返回 null 。
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
| ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { if(!headA || !headB) return nullptr;
ListNode *pa = headA, *pb = headB;
int la = length(headA); int lb = length(headB); if(la > lb) { int diff = la - lb; while(diff--) pa = pa->next; } else { int diff = lb - la; while(diff--) pb = pb->next; }
while(pa && pb) { if(pa == pb) return pa; pa = pa->next; pb = pb->next; }
return nullptr;
}
int length(ListNode* list) { int cnt = 0; ListNode* cur = list; while(cur) { cnt++; cur = cur->next; } return cnt; }
|
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
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
| ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { l1 = revList(l1); l2 = revList(l2); ListNode *t = add(l1, l2); return revList(t); }
ListNode* revList(ListNode* l) { ListNode *pre = nullptr, *cur = l; while(cur != nullptr) { ListNode *t = cur->next; cur->next = pre; pre = cur; cur = t; } return pre; }
ListNode* add(ListNode* l1, ListNode* l2) { ListNode *dummy = new ListNode(-1), *cur = dummy; int carry = 0; while(l1 || l2 || carry) { int sum = (l1? l1->val : 0) + (l2 ? l2->val : 0) + carry; carry = sum/10; sum = sum%10; cur->next = new ListNode(sum); cur = cur->next; if(l1) l1 = l1->next; if(l2) l2 = l2->next; } return dummy->next; }
|
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
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
| ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode *dummy = new ListNode(-1); ListNode *cur = dummy;
priority_queue<ListNode*, vector<ListNode*>, cmp> pq; for(auto node : lists) { if(node != nullptr) { pq.push(node); } }
while(!pq.empty()) { auto t = pq.top(); pq.pop(); cur->next = t; cur = cur->next; if (cur->next) pq.push(cur->next); }
return dummy->next;
}
struct cmp{ bool operator() (ListNode* a, ListNode* b) { return a->val > b->val; } };
|
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
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
| class Solution { public: ListNode* sortList(ListNode* head) { if(!head || !head->next) return head; ListNode *slow = head, *fast = head, *pre = nullptr; while(fast && fast->next) { pre = slow; slow = slow->next; fast = fast->next->next; } pre->next = nullptr; ListNode* half1 = sortList(head); ListNode* half2 = sortList(slow); return mergeList(half1, half2); } ListNode* mergeList(ListNode* l1, ListNode* l2) { ListNode* dummy = new ListNode(-1); ListNode* cur = dummy; while(l1 && l2) { if(l1->val < l2->val) { cur->next = l1; l1 = l1->next; } else { cur->next = l2; l2 = l2->next; } cur = cur->next; } if(l1) cur->next = l1; if(l2) cur->next = l2; return dummy->next; } };
|
给定循环单调非递减列表中的一个点,写一个函数向这个列表中插入一个新元素 insertVal ,使这个列表仍然是循环升序的。
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
| Node* insert(Node* head, int val) { Node *node = new Node(val); if(head == nullptr) { head = node; head->next = head; } else if(head->next == head) { head->next = node; node->next = head; } else { helper(head, node); } return head; }
void helper(Node* head, Node* node) { Node *cur = head, *next = head->next; Node *biggest = head; while(!(cur->val<=node->val && next->val>=node->val) && next!=head) { cur = next; next = next->next; if(cur->val >= biggest->val) { biggest = cur; } } if(cur->val<=node->val && next->val>=node->val) { cur->next = node; node->next= next; } else { node->next = biggest->next; biggest->next = node; } }
|
定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ListNode* oddEvenList(ListNode* head) { if(head == nullptr) { return head; } ListNode *evenHead = head->next; ListNode *odd = head, *even = evenHead; while(even && even->next) { odd->next = even->next; odd = odd->next; even->next = odd->next; even = even->next; } odd->next = evenHead; return head; }
|
L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为:L0 → Ln → L1 → Ln - 1 → L2 → Ln - 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
| void reorderList(ListNode* head) { ListNode *slow = head, *fast = head; while(fast->next && fast->next->next) { fast = fast->next->next; slow = slow->next; } ListNode *last = slow->next, *pre = nullptr; slow->next = nullptr; while(last != nullptr) { ListNode *t = last->next; last->next = pre; pre = last; last = t; } ListNode *left = head, *right = pre; while(left && right) { ListNode *lnext = left->next; ListNode *rnext = right->next; left->next = right; right->next = lnext; left = lnext; right = rnext; } }
|
给定一个已排序的链表的头 head,删除所有重复的元素,使每个元素只出现一次。
递归法
1 2 3 4 5 6 7
| ListNode* deleteDuplicates(ListNode* head) { if(!head || !head->next) return head;
head->next = deleteDuplicates(head->next); return (head->val == head->next->val) ? head->next : head; }
|
迭代法
1 2 3 4 5 6 7 8 9 10 11 12 13
| ListNode* deleteDuplicates(ListNode* head) { ListNode* cur = head; while(cur && cur->next) { if(cur->val == cur->next->val) { cur->next = cur->next->next; } else { cur = cur->next; } }
return head; }
|
给定一个已排序的链表的头head,删除原始链表中所有重复数字的节点,只留下不同的数字。返回已排序的链表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ListNode* deleteDuplicates(ListNode* head) { if (!head || !head->next) return head; ListNode *dummy = new ListNode(-1), *pre = dummy; dummy->next = head; while(pre->next) { ListNode *cur = pre->next; while(cur->next && cur->next->val==cur->val) { cur = cur->next; } if(cur != pre->next) pre->next = cur->next; else pre = pre->next; } return dummy->next; }
|
位我上者,灿烂星空;道德律令,在我心中。