【道德经·第十二章】五色令人目盲,五音令人耳聋,五味令人口爽,驰骋畋(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; }
  | 
 
位我上者,灿烂星空;道德律令,在我心中。