• leetcode Ch5-Linked List


     一、

    1. Remove Duplicates from Sorted List II

     1 class Solution {
     2 public:
     3     ListNode* deleteDuplicates(ListNode* head) {
     4         ListNode* dummy = new ListNode(0);
     5         dummy->next = head;
     6         ListNode* pre = dummy;
     7         ListNode* cur = head;
     8         while (cur != NULL && cur->next != NULL) {
     9             if (cur->val == cur->next->val) {
    10                 while(cur->next != NULL && cur->val == cur->next->val) {
    11                     cur = cur->next;            
    12                 }
    13                 pre->next = cur->next;
    14                 cur = cur->next;
    15             } else {
    16                 pre = pre->next;
    17                 cur = cur->next;
    18             }
    19         }
    20         return dummy->next;
    21     }
    22 };
    View Code

    2. Remove Duplicates from Sorted List

     1 class Solution {
     2 public:
     3     ListNode* deleteDuplicates(ListNode* head) {
     4         ListNode* dummy = new ListNode(0);
     5         dummy->next = head;
     6         ListNode* pre = dummy, *cur = head;
     7         while (cur != NULL && cur->next != NULL) {
     8             if (cur->val == cur->next->val) {
     9                 while (cur->next != NULL && cur->val == cur->next->val) {
    10                     cur = cur->next;
    11                 }
    12                 pre->next = cur;
    13                 pre = pre->next;
    14                 cur = cur->next;
    15             } else {    
    16                 cur = cur->next;
    17                 pre = pre->next;
    18             }    
    19         }
    20         return dummy->next;
    21     }
    22 };
    View Code

     只在1.的基础上改了两句。

     二、

    1. Reverse Linked List 【模板式】

     1 ListNode* reverseList(ListNode* head) {
     2     ListNode* prev = NULL;
     3     while (head != NULL) {
     4         ListNode* next = head->next;
     5         head->next = prev;
     6         prev = head;
     7         head = next;
     8     }
     9     return prev;
    10 }
    View Code

    while循环里和swap很像,上一句的右侧都是下一句的左侧。

    2. Reverse Linked List II

     1 class Solution {
     2 public:
     3     ListNode* reverseBetween(ListNode* head, int m, int n) {
     4         ListNode* dummy = new ListNode(0);
     5         dummy->next = head;
     6         ListNode* prev = dummy;
     7         for (int i = 1; i < m; i++) {
     8             prev = prev->next;
     9         }
    10         head = prev->next;
    11         ListNode* next = head->next;
    12         ListNode* pprev = prev;
    13         ListNode* tail = head;
    14         for (int i = m; i <= n; i++) {  //这部分和reverseList一样
    15             next = head->next;
    16             head->next = prev;
    17             prev = head;
    18             head = next;
    19         }
    20         pprev->next = prev;
    21         tail->next = head;
    22         return dummy->next;
    23     }
    24 };
    View Code

    中间(m, n)区间内reverse和1.里reverseList一样。

     注意:从m到n这几个元素都参与for循环了,包括第m个元素!进行reverse之后,head指向第n+1个元素,prev指向逆转后的新head(从m到n这几个元素中的新head)。

    Partition List

     1 class Solution {
     2 public:
     3     ListNode* partition(ListNode* head, int x) {
     4         ListNode* leftDummy = new ListNode(0);
     5         ListNode* rightDummy = new ListNode(0);
     6         ListNode* left = leftDummy, *right = rightDummy;
     7         while (head != NULL) {
     8             if (head->val < x) {
     9                 left->next =  head;
    10                 left = left->next;
    11             } else {
    12                 right->next = head;
    13                 right = right->next;
    14             }
    15             head = head->next;
    16         }
    17         right->next = NULL;
    18         left->next = rightDummy->next;
    19         return leftDummy->next;
    20     }
    21 };
    View Code

    Merge Two Sorted Lists

     1 class Solution {
     2 public:
     3     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
     4         ListNode* dummy = new ListNode(0);
     5         ListNode* pre = dummy;
     6         while (l1 != NULL && l2 != NULL) {
     7             if (l1->val < l2->val) {
     8                 pre->next = l1;
     9                 l1 = l1->next;
    10             } else {
    11                 pre->next = l2;
    12                 l2 = l2->next;
    13             }
    14             pre = pre->next;
    15         }
    16         if (l1 != NULL) {
    17             pre->next = l1;
    18         }
    19         if (l2 != NULL) {
    20             pre->next = l2;
    21         }
    22         return dummy->next;
    23     }
    24 };
    View Code

    Sort List

    用MergeSort和QuickSort分别实现一下。

    MergeSort用到了findMedian的方法(利用双指针可以达到one-pass找到中点)。

     1 class Solution {
     2 public:
     3     ListNode* findMiddle(ListNode* head) { // 找到的是下标为(n - 1) / 2的点(如果是偶数个数,那就是中间偏左一点的)
     4         ListNode* slow = head, *fast = head->next;
     5         while (fast != NULL && fast->next != NULL) {
     6             slow = slow->next;
     7             fast = fast->next->next;
     8         }
     9         return slow;
    10     }
    11     ListNode* merge(ListNode* l1, ListNode* l2) {
    12         ListNode* dummy = new ListNode(0);
    13         ListNode* pre = dummy;
    14         while (l1 != NULL && l2 != NULL) {
    15             if (l1->val < l2->val) {
    16                 pre->next = l1;
    17                 l1 = l1->next;
    18             } else {
    19                 pre->next = l2;
    20                 l2 = l2->next;
    21             }
    22             pre = pre->next;
    23         }
    24         if (l1 != NULL) {
    25             pre->next = l1;
    26         }
    27         if (l2 != NULL) {
    28             pre->next = l2;
    29         }
    30         return dummy->next;
    31     }
    32     
    33     ListNode* sortList(ListNode* head) {
    34         if (head == NULL || head->next == NULL) {
    35             return head;
    36         }
    37         ListNode* mid = findMiddle(head);    
    38         ListNode* right = sortList(mid->next);
    39         mid->next = NULL;
    40         ListNode* left = sortList(head);
    41          return merge(left, right);
    42     }
    43 };
    View Code

    其中merge即为上一题中的mergeTwoLists.

     注意:findMiddle函数最开始时slow = head, fast = head->next. 通过这种方式可以保证求出来的mid是当有偶数个元素时是中间偏左一点的。

    Reorder List

    【三大链表基本操作:findMiddle,reverse,merge】

     1 class Solution {
     2 public:
     3     ListNode* findMiddle(ListNode* head) {
     4         ListNode* slow = head, *fast = head;
     5         while (fast != NULL && fast->next != NULL) {
     6             slow = slow->next;
     7             fast = fast->next->next;
     8         }
     9         return slow;
    10     }
    11     ListNode* reverseList(ListNode* head) {
    12         ListNode* prev = NULL;
    13         while (head != NULL) {
    14             ListNode* next = head->next;
    15             head->next = prev;
    16             prev = head;
    17             head = next;
    18         }
    19         return prev;
    20     }
    21     ListNode* merge(ListNode* l1, ListNode* l2) {
    22         ListNode* dummy = new ListNode(0);    
    23         ListNode* prev = dummy;
    24         int count = 0;
    25         while (l1 != NULL && l2 != NULL) {
    26             count++;
    27             if (count % 2 == 1) {
    28                 prev->next = l1;
    29                 l1 = l1->next;
    30             } else {
    31                 prev->next = l2;
    32                 l2 = l2->next;
    33             }
    34             prev = prev->next;
    35         }
    36         if (l1 != NULL) {
    37             prev->next = l1;
    38         } else {
    39             prev->next = l2;
    40         }
    41         return dummy->next; 
    42     }
    43     void reorderList(ListNode* head) {
    44         if (head == NULL || head->next == NULL) {
    45             return;
    46         }
    47         ListNode* mid = findMiddle(head);
    48         ListNode* p = reverseList(mid->next);
    49         mid->next = NULL;
    50         merge(head, p);
    51     }
    52 };
    View Code

     Merge k Sorted Lists

    方法1: 利用堆(priority_queue)。每次取出K个队列中的最小值(logK),共取N次,因此复杂度为 NlogK

     1 class Solution {
     2 public:
     3     struct cmp {
     4         bool operator()(ListNode* p, ListNode* q) {
     5             return p->val > q->val;
     6         }
     7     };
     8     
     9     ListNode* mergeKLists(vector<ListNode*> &lists) {
    10         if (lists.empty()) {
    11             return NULL;
    12         }
    13         priority_queue<ListNode*, vector<ListNode*>, cmp> pq;
    14         ListNode* dummy = new ListNode(0);
    15         ListNode* prev = dummy;
    16         for (int i = 0; i < lists.size(); i++) {
    17             if (lists[i] != NULL) {
    18                 pq.push(lists[i]);
    19             }
    20         }
    21         while (!pq.empty()) {
    22             ListNode* tmp = pq.top();
    23             prev->next = tmp;
    24             prev = tmp;
    25             pq.pop();
    26             if (tmp->next != NULL) {
    27                 pq.push(tmp->next);
    28             }
    29         }
    30         return dummy->next;
    31     }
    32 };
    View Code

    方法2:分治。【自顶向下】

     1 class Solution {
     2 public:
     3     ListNode* mergeKLists(vector<ListNode*> &lists) {
     4         if (lists.empty()) {
     5             return NULL;
     6         }
     7         return mergeHelper(lists, 0, lists.size() - 1);
     8     }
     9     
    10     ListNode* mergeHelper(vector<ListNode*> &lists, int start, int end) {
    11         if (start == end) {
    12             return lists[start];
    13         }
    14         int mid = start + (end - start) / 2;
    15         ListNode* left = mergeHelper(lists, start, mid);
    16         ListNode* right = mergeHelper(lists, mid + 1, end);
    17         return mergeTwoLists(left, right);    
    18     }
    19     
    20     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    21         ListNode* dummy = new ListNode(0);
    22         ListNode* prev = dummy;
    23         while (l1 != NULL && l2 != NULL) {
    24             if (l1->val < l2->val) {
    25                 prev->next = l1;
    26                 l1 = l1->next;
    27             } else {
    28                 prev->next = l2;
    29                 l2 = l2->next;
    30             }
    31             prev = prev->next;
    32         }
    33         if (l1 != NULL) {
    34             prev->next = l1;
    35         } else {
    36             prev->next = l2;
    37         }
    38         return dummy->next;
    39     }
    40 };
    View Code

    注意:不要忘了判空!这种边界条件要谨慎!谨记!

     Linked List Cycle

     1 class Solution {
     2 public:
     3     bool hasCycle(ListNode* head) {
     4         if (head == NULL) {
     5             return false;
     6         }
     7         ListNode* slow = head, *fast = head;
     8         while (fast && fast->next) {
     9             slow = slow->next;    
    10             fast = fast->next->next;
    11             if (slow == fast) {
    12                 return true;
    13             }
    14         }
    15         return false;
    16     }
    17 };
    View Code

     Linked List Cycle II

     1 class Solution {
     2 public:
     3     ListNode* detectCycle(ListNode* head) {
     4         ListNode* slow = head, *fast = head;
     5         while (fast && fast->next) {
     6             slow = slow->next;
     7             fast = fast->next->next;
     8             if (slow == fast) {
     9                 while (head != slow) {
    10                     head = head->next;
    11                     slow = slow->next;
    12                 }
    13                 return slow;
    14             }
    15         }
    16         return NULL;
    17     }
    18 };
    View Code

    Copy List with Random Pointer

     1 class Solution {
     2 public:
     3     
     4     void copyNext(RandomListNode* head) {
     5         RandomListNode* pre = head;
     6         while (pre != NULL) {
     7             RandomListNode* tmp = new RandomListNode(pre->label);
     8             tmp->next = pre->next;
     9             pre->next = tmp;
    10             pre = pre->next->next;
    11         }
    12     }
    13     void copyRandom(RandomListNode* head) {
    14         RandomListNode* pre = head;
    15         while (pre != NULL) {
    16             if (pre->random != NULL) { // don't forget
    17                 pre->next->random = pre->random->next;
    18             }
    19             pre = pre->next->next;
    20         }
    21     }
    22     
    23     RandomListNode* splitList(RandomListNode* head) {
    24         RandomListNode* newHead = head->next;
    25         RandomListNode* q = newHead;
    26         while (head != NULL) {
    27             head->next = q->next;
    28             head = head->next;
    29             if (head) { // don't forget
    30                 q->next = head->next;
    31             }
    32             q = q->next;
    33         }
    34         return newHead;
    35     }
    36     
    37     RandomListNode* copyRandomList(RandomListNode* head) {
    38         if (head == NULL) {
    39             return NULL;
    40         }
    41         copyNext(head);
    42         copyRandom(head);
    43         return splitList(head);
    44     }
    45 };
    View Code

    注意!处理链表题很重要的一点是:在对一个指针p取next时,首先要确保 p!=NULL 

    Clone Graph

    Convert Sorted List to Binary Search Tree

    Convert Binary Tree to Doubly Linked List

    Reverse Nodes in k-Group

    Heapify 堆化

    =================================================

      24 Swap Nodes in Pairs 32.4% Medium
      148   22.2% Medium
      61 Rotate List 21.7% Medium
      25   25.4% Hard
      206   31.9% Easy
      92   26.0% Medium
      143   21.0% Medium
      19 Remove Nth Node From End of List 27.0% Easy
      203 Remove Linked List Elements 25.9% Easy
      83   34.5% Easy
      82   25.0% Medium
      86   27.4% Medium
      234 Palindrome Linked List 22.6% Easy
      21   32.6% Easy
      23   21.1% Hard
      141   36.3% Medium
      142   31.4% Medium
      160 Intersection of Two Linked Lists 28.7% Easy
      147 Insertion Sort List 26.6% Medium
      237 Delete Node in a Linked List 46.7% Easy
      138   25.2% Hard
      109   27.9% Medium
      2 Add Two Numbers 20.7% Medium

    [剑指offer] 两个链表的第一个公共节点

     1 class Solution {
     2 public:
     3     ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {
     4         ListNode* p = pHead1;
     5         int count1 = 0, count2 = 0;
     6         while (p != NULL) {
     7             count1++;
     8             p = p->next;
     9         }
    10         p = pHead2;
    11         while (p != NULL) {
    12             count2++;
    13             p = p->next;
    14         }
    15         if (count1 < count2) {
    16             return findNode(pHead1, count1, pHead2, count2);    
    17         } else {
    18             return findNode(pHead2, count2, pHead1, count1);
    19         }
    20     }
    21 
    22     ListNode* findNode(ListNode* pHead1, int count1, ListNode* pHead2, int count2) {
    23         if (pHead1 == NULL) {
    24             return NULL;
    25         }
    26         int tmp = count2 - count1;
    27         ListNode* p2 = pHead2, *p1 = pHead1;
    28         while (tmp--) {
    29             p2 = p2->next;
    30         }
    31         while (p1 != NULL && p1 != p2) {
    32             p1 = p1->next;
    33             p2 = p2->next;
    34         }
    35         return p1;
    36     }
    37 };
    View Code

    参考剑指offer P193. 本题说的“公共节点”不是指“值相等”,而是“同一个节点”。即两链表在该点处汇合。

  • 相关阅读:
    JavaScript autoComplete 1.2
    Linux下安装配置git
    《SQL Server 2008从入门到精通》20180627
    《SQL必知必会》知识点汇总
    关于js的setTimeout和setInterval
    关于js的闭包
    web图片类型
    关于绑定事件
    js原型与继承
    关于js的mouseout
  • 原文地址:https://www.cnblogs.com/forcheryl/p/4674458.html
Copyright © 2020-2023  润新知