zoukankan      html  css  js  c++  java
  • 【LeetCode】链表 linked list(共34题)

    【2】Add Two Numbers (2018年11月30日,第一次review,ko)

    两个链表,代表两个整数的逆序,返回一个链表,代表两个整数相加和的逆序。

    Example:
    Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
    Output: 7 -> 0 -> 8
    Explanation: 342 + 465 = 807.
     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    12         if (!l1 || !l2) {
    13             return l1 == nullptr ? l2 : l1;
    14         }
    15         ListNode *h1 = l1, *h2 = l2;
    16         ListNode *head = 0, *tail = 0;
    17         int carry = 0;
    18         while (h1 && h2) {
    19             int num = h1->val + h2->val + carry;
    20             carry = num / 10, num %= 10;
    21             ListNode* node = new ListNode(num);
    22             if (!head) {
    23                 tail = head = node;
    24             } else {
    25                 tail = tail->next = node;
    26             }
    27             h1 = h1->next, h2 = h2->next;
    28         }
    29         while (h1) {
    30             int num = h1->val + carry;
    31             carry = num / 10, num %= 10;
    32             ListNode* node = new ListNode(num);
    33             tail = tail->next = node;
    34             h1 = h1->next;
    35         }
    36         while (h2) {
    37             int num = h2->val + carry;
    38             carry = num / 10, num %= 10;
    39             ListNode* node = new ListNode(num);
    40             tail = tail->next = node;
    41             h2 = h2->next;
    42         }
    43         if (carry) {
    44             ListNode* node = new ListNode(carry);
    45             carry = 0;
    46             tail = tail->next = node;
    47         }
    48         return head;
    49     }
    50 };
    View Code

    【19】Remove Nth Node From End of List (2018年10月30日 算法群)

    给了一个链表,从尾部删除第 N 个结点。

    题解:two pointers,fast 先走 N 步,然后slow,fast 一起走,fast走到最后一个非空结点,slow就走到了要删除结点的前一个结点。(注意有个特判情况是如果第N个结点是头节点,那么要特殊处理)

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* removeNthFromEnd(ListNode* head, int n) {
    12         if (!head) {return head;}
    13         ListNode *fast = head, *slow = head;
    14         //1. fast goes n steps first
    15         for (int k = 0; k < n && fast; ++k) {
    16             fast = fast->next;
    17         }
    18         //2. both slow and fast move simultaneously until fast to the end of the list
    19         if (fast) {
    20             while (fast->next) {
    21                 slow = slow->next;
    22                 fast = fast->next;
    23             }
    24             slow->next = slow->next->next;
    25         } else {
    26             head = head->next;
    27         }
    28         return head;
    29     }
    30 };
    View Code 

     

    【21】Merge Two Sorted Lists 

    合并两个有序链表变成一个大链表,大链表要求有序。(归并排序)

    题解:无,直接归并

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    12         if (!l1) {return l2;}
    13         if (!l2) {return l1;}
    14         ListNode *p1 = l1, *p2 = l2, *head = 0, *tail = 0;
    15         while (p1 && p2) {
    16             if (p1->val < p2->val) {
    17                 if(!head) {
    18                     tail = head = p1;
    19                 } else {
    20                     tail = tail->next = p1;
    21                 }
    22                 p1 = p1->next;
    23             } else {
    24                 if (!head) {
    25                     tail = head = p2;
    26                 } else {
    27                     tail = tail->next = p2;
    28                 }
    29                 p2 = p2->next;
    30             }
    31         }
    32         //这里其实不用遍历了,直接连起来ok
    33         if (p1) {
    34             tail->next = p1;
    35         }
    36         if (p2) {
    37             tail->next = p2;
    38         }
    39         return head;
    40     }
    41 };
    View Code

     

    【23】Merge k Sorted Lists

    给了k个已经排好序的链表,要返回一个综合排序的大链表(归并排序)

    题解:用 prioprity_queue 的运算符()重载来实现比较函数。具体运算符重载的实现方法见代码。(奇怪的是为啥pq的cmp函数要写 > ,pq里面才是从小到大排序?)

    这个题目其实应该复习 priority_queue 的比较函数的实现方法。(要搞懂原理。)

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     //好奇怪,为啥这里要写大于符号,pq才是从小到大排序... ????
    12     struct cmp{
    13         bool operator() (const ListNode* node1, const ListNode* node2) {
    14             return node1->val > node2->val;
    15         }
    16     };
    17 
    18     ListNode* mergeKLists(vector<ListNode*>& lists) {
    19         const int n = lists.size();
    20         if (n == 0) {return NULL;}
    21         vector<ListNode*> ptr(n, NULL);
    22         for (int i = 0; i < n; ++i) {
    23             ptr[i] = lists[i];
    24         }
    25         ListNode *head = 0, *tail = 0;
    26         priority_queue<ListNode*, vector<ListNode*>, cmp> pq;
    27         for (int i = 0; i < n; ++i) {
    28             if (!ptr[i]) {continue;} //注意这里有可能有的链表头节点为空,要特判
    29             pq.push(ptr[i]);
    30             ptr[i] = ptr[i]->next;
    31         }
    32         while (!pq.empty()) {
    33             ListNode* node = pq.top();
    34             pq.pop();
    35             if (node->next) { pq.push(node->next); }
    36             if (!head) {
    37                 tail = head = node;
    38             } else {
    39                 tail = tail->next = node;
    40             }
    41         }
    42         return head;
    43     }
    44 };
    View Code

     

    【24】Swap Nodes in Pairs (2018年12月1日,第一次复习,没有ko,需要再次复习)

    给了一个链表,交换两个相邻的元素。

    Given 1->2->3->4, you should return the list as 2->1->4->3. 
     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* swapPairs(ListNode* head) {
    12         if (!head) {return head;}
    13         ListNode* pre = 0, *cur1 = head, *cur2 = cur1->next, *ne = 0;
    14         ListNode* h1 = 0;
    15         while (cur2) {
    16             ne = cur2->next;
    17             cur2->next = cur1;
    18             cur1->next = ne;
    19             pre = cur1;
    20             if (!h1) {h1 = cur2;}
    21             cur1 = ne;
    22             cur2 = cur1 == nullptr ? nullptr : cur1->next;
    23             pre->next = cur2 == nullptr ? cur1 : cur2;
    24         }
    25         return h1 == nullptr ? head : h1;
    26     }
    27 };
    View Code

    【25】Reverse Nodes in k-Group ()

    【61】Rotate List (2018年12月1日,第一次复习,ko,注意边界条件,k = 0 的情况特判)

    把一个单链表循环左移k个单位,返回新链表。

    Input: 0->1->2->NULL, k = 4
    Output: 2->0->1->NULL
    Explanation:
    rotate 1 steps to the right: 2->0->1->NULL
    rotate 2 steps to the right: 1->2->0->NULL
    rotate 3 steps to the right: 0->1->2->NULL
    rotate 4 steps to the right: 2->0->1->NULL

    题解:先走到要左移的第k个结点的前面一个结点,这个结点就是尾部结点,然后把下一个结点当作头结点,做几个指针的赋值操作。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* rotateRight(ListNode* head, int k) {
    12         //1. 先求长度
    13         int len = getLen(head);
    14         if (len == 0 || k ==0) {return head;}
    15         if (k >= len) { k %= len; }
    16         if (k == 0) {return head;}
    17         //2. 计算应该往前走几步
    18         int step = len - k -1;
    19         ListNode* cur = head;
    20         for (int i = 0; i < step; ++i) {
    21             cur = cur->next;
    22         }
    23         //3. 标记头尾指针。尾指针就是走了step步的结点cur,头指针是cur的next结点。
    24         ListNode* tail = cur, *h1 = cur->next;
    25         tail->next = 0;
    26         cur = h1;
    27         while (cur->next) {
    28             cur = cur->next;
    29         }
    30         cur->next = head;
    31         return h1;
    32     }
    33     int getLen(ListNode* head) {
    34         int ret = 0;
    35         ListNode* cur = head;
    36         while (cur) {
    37             ret++;
    38             cur = cur->next;
    39         }
    40         return ret;
    41     }
    42 };
    View Code

    【82】Remove Duplicates from Sorted List II (2018年12月1日,第一次复习,有边界没有想到)

    删除一个链表里面的重复结点,(重复结点不保留),返回头结点。

    题解:用一个cnt变量记录当前结点出现了几次,如果只出现一次就把在加上。有个小的解题点需要注意,就是如果输入是 [1,2,2] 这种的话,最后的尾结点不是最后的结点这种,每次都要执行 tail->next = 0,来避免这种case。 

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* deleteDuplicates(ListNode* head) {
    12         ListNode *h1 = 0, *tail = 0;
    13         ListNode *pre = head, *cur = head;
    14         while (pre) {
    15             cur = pre->next;
    16             int cnt = 1;  //用一个变量标记当前结点有几个重复的
    17             while (pre && cur && pre->val == cur->val) {
    18                 cur = cur->next;
    19                 ++cnt;
    20             }
    21             if (cnt == 1) {
    22                 if (!h1) {
    23                     tail = h1 = pre;
    24                 } else {
    25                     tail = tail->next = pre;
    26                 }
    27                 tail->next = 0;  //如果当前结点后面有一堆重复的数的话,那么其实当前结点就是尾结点 [1,2,2]
    28             }
    29             if (cur) { 
    30                 pre = cur; 
    31             } else {
    32                 pre = 0;
    33             }
    34         }
    35         return h1;
    36     }
    37 };
    View Code

    【83】Remove Duplicates from Sorted List (2018年12月1日,第一次复习,ko)

    删除一个链表里面的重复结点(重复结点保留一个,目标是所有结点distinct),返回头结点。

    题解:用两根指针遍历,pre指针保存第一次出现的当前元素,cur指针一直往后遍历,直到下一个第一次出现的元素。 

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* deleteDuplicates(ListNode* head) {
    12         ListNode *h1 = head;
    13         ListNode *pre = head, *cur = head, *ne = 0;
    14         while (cur) {
    15             cur = cur->next;
    16             while (pre && cur && pre->val == cur->val) {
    17                 cur = cur->next;
    18             }
    19             pre->next = cur;
    20             pre = cur;
    21         }
    22         return h1;
    23     }
    24 };
    View Code

    【86】Partition List (2018年12月1日,第一次复习,写的有bug,需要二次复习)

    把单向链表按给定的值 x 划分成小于x的结点在左边,大于等于 x 的结点在右边的样子。

    题解:(类似题)把一个数组按照给定的值 x 划分成左边小,中间相等,右边大的样子。(这个题叫做荷兰国旗问题,也是快速排序的 partition)。

    说回这道题,我先把链表拆成两个,一个是小于 x 的值的链表,一个是大于等于 x 值的链表(拆的时候注意执行 tail->next = 0 的时候,下一个结点一定要用指针提前标记起来,不然下一个结点就丢了)。然后把这两个连接起来就ok了。 

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* partition(ListNode* head, int x) {
    12         vector<ListNode*> h(2, nullptr);
    13         vector<ListNode*> tail(2, nullptr);
    14         ListNode* cur = head, *ne = 0;
    15         while (cur) {
    16             ne = cur->next;  //先用一个指针标记下一个结点,不然执行 tail[i]->next = 0 的时候相当于 cur->next = 0。
    17             if (cur->val < x) {
    18                 if (!h[0]) {
    19                     tail[0] = h[0] = cur;
    20                 } else {
    21                     tail[0] = tail[0]->next = cur;
    22                 }
    23                 tail[0]->next = 0;
    24             } else {
    25                 if (!h[1]) {
    26                     tail[1] = h[1] = cur;
    27                 } else {
    28                     tail[1] = tail[1]->next = cur;
    29                 }
    30                 tail[1]->next = 0;
    31             }
    32             cur = ne;  
    33         }
    34         ListNode* ret = 0, *t = 0;
    35         for (int i = 0; i < 2; ++i) {
    36             if (!h[i]) {continue;}
    37             if (!ret) {
    38                 ret = h[i];
    39                 t = tail[i];
    40             } else {
    41                 t->next = h[i];
    42                 t = tail[i];
    43             }
    44         }
    45         return ret;
    46     }
    47 };
    View Code

    【92】Reverse Linked List II (2018年12月1日,第一次复习,需要调试)

    把单链表上的第 m 个结点到第 n 个结点这一部分进行反转,m,n是整数,1 ≤ m ≤ n ≤ length of list.

    Example:
    Input: 1->2->3->4->5->NULL, m = 2, n = 4
    Output: 1->4->3->2->5->NULL

    题解:本题需要分类其实,我一开始只想了最普通那种,当 m 不等于 1 的时候,这个时候相当于我先走了 m-1 步,用一个指针标记第 m 个结点的前一个结点,然后从第 m 个结点开始反转 k 个结点(k = n-m+1)。

    然而当 m =1 的时候相当于反转整个链表,需要分类处理。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* reverseBetween(ListNode* head, int m, int n) {
    12         const int k = n - m + 1;
    13         ListNode* newHead = 0;
    14         if (m == 1) {
    15             newHead = reverse(&head, k);
    16         } else {
    17             ListNode* cur = head;
    18             for (int i = 1; i < m-1; ++i) {
    19                 cur = cur->next;
    20             }
    21             ListNode* pre = cur;
    22             pre->next = reverse(&cur->next, k);
    23             newHead = head;
    24         }
    25         return newHead;
    26     }
    27     ListNode* reverse(ListNode** head, const int k) {
    28         ListNode *pre = 0, * cur = *head, * ne = 0;
    29         ListNode *tail = 0;
    30         for (int i = 0; i < k && cur; ++i) {
    31             ne = cur->next;
    32             cur->next = pre;
    33             pre = cur;
    34             if (!tail) {tail = cur;}
    35             cur = ne;
    36         } 
    37         tail->next = cur;
    38         return pre;
    39     }
    40     
    41 };
    View Code

    【109】Convert Sorted List to Binary Search Tree (2018年12月1日,第一次复习,WA了一次)

    把一个有序的链表拍成一棵高度平衡的二叉树。

    Example:
    Given the sorted linked list: [-10,-3,0,5,9],
    One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
          0
         / 
       -3   9
       /   /
     -10  5

    题解:我们先用快慢指针找到链表中间的结点,(如果是奇数个结点就指向中心的结点,如果是偶数个结点就指向中间两个结点中靠后的那个结点,这样生成的左子树可能比右子树高度多1)。然后把中间结点当作根结点。递归生成左右子树。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 /**
    10  * Definition for a binary tree node.
    11  * struct TreeNode {
    12  *     int val;
    13  *     TreeNode *left;
    14  *     TreeNode *right;
    15  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
    16  * };
    17  */
    18 class Solution {
    19 public:
    20     TreeNode* sortedListToBST(ListNode* head) {
    21         if (!head) {return nullptr;}
    22         ListNode* slow = head, *fast = head;
    23         ListNode* pre = 0;
    24         while (fast && fast->next) {
    25             pre = slow;
    26             slow = slow->next;
    27             fast = fast->next->next;
    28         }
    29         TreeNode* root = new TreeNode(slow->val);
    30         if (pre) {pre->next = 0;}
    31         if (pre != 0) {  //如果只有单个结点的话,再次调用生成左子树没有任何意义。
    32             root->left = sortedListToBST(head);
    33         }
    34         root->right = sortedListToBST(slow->next);
    35         return root;
    36     }
    37 };
    View Code

    【138】Copy List with Random Pointer (2018年12月1日,第一次复习)

    复制含有随机指针结点的链表。一种特殊的链表结点类描述如下:

    //Definition for singly-linked list with a random pointer.
    struct RandomListNode {
        int label;
        RandomListNode *next, *random;
        RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
    };

    rand指针是ListNode类中新增的指针,这个指针可能指向整个链表中的任何一个结点,也可能指向 null, 给定有这种种类的节点组成的链表头部,请完成该链表的拷贝。

    题解:解法一:可以用 map 标记。类似于这种结构 ({1 -> 1'}, {2 -> 2'}, {3->3'})。

    解法二:把新拷贝的结点放在原始结点的后面,就是类似于 1 -> 1' -> 2 -> 2' -> 3 -> 3'。然后把 rand 指针串好。在把新旧链表分离出来(本题就要求原来链表出去的时候不能被改变)。

     1 /**
     2  * Definition for singly-linked list with a random pointer.
     3  * struct RandomListNode {
     4  *     int label;
     5  *     RandomListNode *next, *random;
     6  *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     RandomListNode *copyRandomList(RandomListNode *head) {
    12         if (!head) {return head;}
    13         //1. copy list without rand ptr
    14         RandomListNode *cur = head, *ne = 0;
    15         while (cur) {
    16             ne = cur->next;
    17             RandomListNode* node = new RandomListNode(cur->label);
    18             cur->next = node;
    19             node->next = ne;
    20             cur = ne;
    21         }
    22         //2. copy rand ptr
    23         cur = head, ne = 0;
    24         while (cur) {
    25             ne = cur->next->next;
    26             if (cur->random) {
    27                 cur->next->random = cur->random->next;
    28             }
    29             cur = ne;
    30         }
    31         //3. split listnode, should recover ori listnode
    32         cur = head;
    33         RandomListNode* h1 = 0, *t1 = 0;
    34         RandomListNode* h2 = 0, *t2 = 0;
    35         while (cur) {
    36             ne = cur->next->next;
    37             if (!h1 && !h2) {
    38                 t1 = h1 = cur->next;
    39                 t2 = h2 = cur;
    40             } else {
    41                 t1 = t1->next = cur->next;
    42                 t2 = t2->next = cur;
    43             }
    44             t1->next = 0;
    45             t2->next = 0;
    46             cur = ne;
    47         }
    48         head = h2;
    49         return h1;
    50     }
    51 };
    View Code

    【141】Linked List Cycle (2019年2月20日)

    判断一个linkedlist是不是有环。

    题解:快慢指针。如果快慢指针能够相遇,就是有环。否则没有。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     bool hasCycle(ListNode *head) {
    12         if (!head) {return false;}
    13         ListNode *slow = head, *fast = head;
    14         while (fast && fast->next) {
    15             slow = slow->next;
    16             fast = fast->next->next;
    17             if (slow == fast) {
    18                 return true;
    19             }
    20         }
    21         return false;
    22     }
    23 };
    View Code

    【142】Linked List Cycle II (2019年2月20日)

    判断一个linkedlist是不是有环,如果有环的话,返回环的起点。

    题解:算法是先让快慢指针相遇,相遇之后慢指针回到头结点,然后两根指针同时走一步,再次相遇就是环的起点。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 //算法是先让快慢指针相遇,相遇之后慢指针回到头结点,然后两根指针同时走一步,再次相遇就是环的起点。
    10 class Solution {
    11 public:
    12     ListNode *detectCycle(ListNode *head) {
    13         if (!head) {return nullptr;}
    14         ListNode *slow = head, *fast = head;
    15         while (fast && fast->next) {
    16             slow = slow->next;
    17             fast = fast->next->next;
    18             if (slow == fast) {
    19                 slow = head;
    20                 while (slow != fast) {
    21                     slow = slow->next;
    22                     fast = fast->next;
    23                 }
    24                 return slow;
    25             }
    26         }
    27         return nullptr;
    28     }
    29 };
    View Code

    【143】Reorder List (2018年12月1日,第一次review,ko) 

    Given a singly linked list L: L0→L1→…→Ln-1→Ln,
    reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… 

    Example 1:
    Given 1->2->3->4, reorder it to 1->4->2->3.
    Example 2:
    Given 1->2->3->4->5, reorder it to 1->5->2->4->3.

    题解:先按照快慢指针拆分成两个链表,reverse 后面半个链表,然后再拼起来。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     void reorderList(ListNode* head) {
    12         if (!head) {return;}
    13         ListNode* slow = head, *fast = head, *pre = 0;
    14         while (fast && fast->next) {
    15             pre = slow;
    16             slow = slow->next;
    17             fast = fast->next->next;
    18         }
    19         if (fast && !fast->next) { //奇数个结点
    20             pre = slow;
    21             slow = slow->next;
    22         }
    23         pre->next = 0;
    24         ListNode* cur2 = reverse(slow), *cur1 = head;
    25         if (!cur2) {return;}  //只有一个结点
    26         ListNode *h1 = 0, *t1 = 0;
    27         while (cur1 && cur2) {
    28             if (!h1) {
    29                 t1 = h1 = cur1;
    30                 cur1= cur1->next;
    31             } else {
    32                 t1 = t1->next = cur1;
    33                 cur1 = cur1->next;
    34             }
    35             t1 = t1->next = cur2;
    36             cur2 = cur2->next;
    37         }
    38         if (cur1) {
    39             t1 = t1->next = cur1;
    40         } else if (cur2) {
    41             t1= t1->next = cur2;
    42         }
    43         head = h1;
    44         return;   
    45     }
    46     ListNode* reverse(ListNode* head) {
    47         ListNode *pre = 0, *cur = head, *ne = 0;
    48         while (cur) {
    49             ne = cur->next;
    50             cur->next = pre;
    51             pre = cur;
    52             cur = ne;
    53         }
    54         return pre;
    55     }
    56 };
    View Code

    【147】Insertion Sort List 

    【148】Sort List 

    【160】Intersection of Two Linked Lists (2018年12月1日,第一次review, ko)

    找到两个链表的公共部分的第一个结点。没有公共部分返回空结点。

    A:          a1 → a2
                       ↘
                         c1 → c2 → c3
                       ↗            
    B:     b1 → b2 → b3

    题解:分别获取两个链表的长度,让长的那个链表走的和短的一样长的位置,然后两个一起走。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    12         int l1 = getLen(headA), l2 = getLen(headB);
    13         int diff = 0;
    14         ListNode *cur1 = headA, *cur2 = headB;
    15         if (l1 > l2) {
    16             diff = l1 - l2;
    17             for (int i = 0; i < diff; ++i) {
    18                 cur1 = cur1->next;
    19             }
    20         } else if (l1 < l2) {
    21             diff = l2 - l1;
    22             for (int i = 0; i < diff; ++i) {
    23                 cur2 = cur2->next;
    24             }
    25         }
    26         while (cur1 && cur2) {
    27             if (cur1 == cur2) {
    28                 return cur1;
    29             }
    30             cur1 = cur1->next;
    31             cur2 = cur2->next;
    32         }
    33         return nullptr;
    34     }
    35     int getLen(ListNode* head) {
    36         ListNode* cur = head;
    37         int cnt = 0;
    38         while (cur) {
    39             cur = cur->next;
    40             cnt++;
    41         }
    42         return cnt;
    43     }
    44 };
    View Code

    【203】Remove Linked List Elements 

    【206】Reverse Linked List (2019年2月24日)

    反转一个链表。

    题解:使用 recursive方法 和 iterative方法。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* reverseList(ListNode* head) {
    12         if (!head || !head->next) { return head; }
    13         ListNode* nextNode = head->next;
    14         ListNode* newHead = reverseList(nextNode);
    15         nextNode->next = head;
    16         head->next = nullptr;
    17         return newHead;
    18     }
    19 };
    View Code
     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* reverseList(ListNode* head) {
    12         ListNode *pre=0, *cur=head, *ne=0;
    13         while(cur){
    14             ne = cur->next;
    15             cur->next = pre;
    16             pre = cur;
    17             cur = ne;
    18         }
    19         return pre;
    20     }
    21 };
    View Code

    【234】Palindrome Linked List 

    【237】Delete Node in a Linked List 

    【328】Odd Even Linked List 

    【369】Plus One Linked List   (2018 年11月26日)

    给一个头结点是高位数字的链表整数加一。返回新链表。

    题解:普通解法可以先搞成一个string 或者vector,再做高精度加。我是先翻转链表,然后加一,然后再翻转一次。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* plusOne(ListNode* head) {
    12         if (!head) {return head;}
    13         h1 = head;
    14         h1 = reverseListNode();
    15         ListNode* cur = h1, *pre = 0;
    16         int carry = 0;
    17         while (carry == 1 && cur || cur == h1) {
    18             int num = cur == h1 ? cur->val + 1 : carry + cur->val;
    19             cur->val = num % 10;
    20             carry = num / 10;
    21             pre = cur;
    22             cur = cur->next;
    23         }
    24         if (carry) {
    25             pre->next = new ListNode(carry);
    26         }
    27         h1 = reverseListNode();
    28         return h1;
    29     }
    30     ListNode* h1;
    31     ListNode* reverseListNode() {
    32         if (!h1) {return h1;}
    33         ListNode* pre = 0, *cur = h1, *next = cur->next;
    34         while (cur) {
    35             next = cur->next;
    36             cur->next = pre;
    37             pre = cur;
    38             cur = next;
    39         }
    40         return pre;
    41     }
    42 };
    View Code

    【379】Design Phone Directory 

    【426】Convert Binary Search Tree to Sorted Doubly Linked List 

    【430】Flatten a Multilevel Doubly Linked List 

    【445】Add Two Numbers II (2018年11月26日)

    给了两个链表,每个链表代表一个数,头结点代表最高位的数字,求两个链表的累加和,返回一个链表。(题目要求不能翻转链表)

    Follow up:
    What if you cannot modify the input lists? In other words, reversing the lists is not allowed.
    
    Example:
    Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
    Output: 7 -> 8 -> 0 -> 7

    题解:我是分别遍历两个链表,然后存在了两个string里面,string里面做高精度加法。然后把结果的string再搞成一个链表,返回。(也可以把string搞成vector,一样的)

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    12         if (l1 == nullptr || l2 == nullptr) {
    13             return l1 == nullptr ? l2 : l1;
    14         }
    15         string s1 = List2Str(l1), s2 = List2Str(l2);
    16         string s3 = addString(s1, s2);
    17         ListNode *head = 0, *tail = 0;
    18         for (int i = 0; i < s3.size(); ++i) {
    19             ListNode* node = new ListNode((s3[i] - '0'));
    20             if (!head) {
    21                 tail = head = node;
    22             } else {
    23                 tail = tail->next = node;
    24             }
    25         }
    26         return head;
    27     }
    28     string List2Str(ListNode* head) {
    29         ListNode* h1 = head;
    30         string ret = "";
    31         while (h1) {
    32             ret += to_string(h1->val);
    33             h1 = h1->next;
    34         }
    35         return ret;
    36     }
    37     string addString(const string& s1, const string& s2) {
    38         int carry = 0;
    39         string ret = "";
    40         int size = min(s1.size(), s2.size());
    41         int s1size = s1.size(), s2size = s2.size();
    42         for (int k = 1; k <= size; ++k) {
    43             int num = (s1[s1size-k] - '0') + (s2[s2size-k] - '0') + carry;
    44             string str = to_string(num % 10);
    45             carry = num / 10;
    46             ret =  str + ret;
    47         }
    48         if (size < s1size) {
    49             const int leftsize = s1size - size;
    50             for (int i = leftsize - 1; i >= 0; --i) {
    51                 int num = (s1[i] - '0') + carry;
    52                 string str = to_string(num % 10);
    53                 carry = num / 10;
    54                 ret = str + ret;
    55             }
    56         } else if (size < s2size) {
    57             const int leftsize = s2size - size;
    58             for (int i = leftsize - 1; i >= 0; --i) {
    59                 int num = (s2[i] - '0') + carry;
    60                 string str = to_string(num % 10);
    61                 carry = num / 10;
    62                 ret = str + ret;
    63             }
    64         }
    65         if (carry) {
    66             ret = to_string(carry) + ret;
    67         }
    68         return ret;
    69     }
    70 };
    View Code

    【707】Design Linked List 

    【708】Insert into a Cyclic Sorted List 

    【725】Split Linked List in Parts (2018年11月26日)

    把一个链表分解成 k 个parts, 要求每个 parts 均匀分布,就是任意两个部分之间的长度不能相差大于一。

    Return a List of ListNode's representing the linked list parts that are formed.
    Examples 1->2->3->4, k = 5 // 5 equal parts [ [1], [2], [3], [4], null ]
    Example 1:
    Input: 
    root = [1, 2, 3], k = 5
    Output: [[1],[2],[3],[],[]]
    Explanation:
    The input and each element of the output are ListNodes, not arrays.
    For example, the input root has root.val = 1, root.next.val = 2, 
    oot.next.next.val = 3, and root.next.next.next = null.
    The first element output[0] has output[0].val = 1, output[0].next = null.
    The last element output[4] is null, but it's string representation as a ListNode is [].
    Example 2:
    Input: 
    root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3
    Output: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
    Explanation:
    The input has been split into consecutive parts with size difference at most 1, and earlier parts are a larger size than the later parts.

    题解:先算总长度,然后把每个部分最短的长度算出来base,再把有几个部分需要加一算出来addition,然后开始分解就好啦。主要注意分解完了之后tail->next  要指向空指针。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     vector<ListNode*> splitListToParts(ListNode* root, int k) {
    12         vector<ListNode*> ret;
    13         int n = getLen(root);
    14         int base = n / k;
    15         int addition = n % k;
    16         ListNode* head = root;
    17         for (int i = 0; i < addition; ++i) { //base + 1
    18             const int tot = base + 1;
    19             ListNode *h1 = 0, *t1 = 0;
    20             for (int j = 0; j < tot; ++j) {
    21                 if (h1 == 0) {
    22                     t1 = h1 = head;
    23                 } else {
    24                     t1 = t1->next = head;
    25                 }
    26                 head = head->next;
    27             }
    28             if(t1) {t1->next = 0;}
    29             ret.push_back(h1);
    30         }
    31         for (int i = 0; i < k - addition; ++i) { //base
    32             const int tot = base;
    33             ListNode* h1 = 0, *t1 = 0;
    34             for (int j = 0; j < tot; ++j) {
    35                 if (h1 == 0) {
    36                     t1 = h1 = head;
    37                 } else {
    38                     t1 = t1->next = head;
    39                 }
    40                 head = head->next;
    41             }
    42             if (t1) {t1->next = 0;}
    43             ret.push_back(h1);
    44         }
    45         return ret;
    46     }
    47     int getLen(ListNode* root) {
    48         ListNode* head = root;
    49         if (!head) {return 0;}
    50         int ret = 0;
    51         while (head) {
    52             ret++;
    53             head = head->next;
    54         }
    55         return ret;
    56     }
    57     /*
    58     void print(ListNode* h1) {
    59         ListNode* head = h1;
    60         while (head) {
    61             printf("%d -> ", head->val);
    62             head = head->next;
    63         }
    64     }
    65     */
    66 };
    View Code

    【817】Linked List Components (2019年2月9日,谷歌tag复习)(M)

    给了一个链表和一个集合G(G是链表元素的子集),如果在链表中两个相邻的元素算一个component,返回这个集合G中有多少个component。

    题解:遍历链表,如果当前的结点在G中的话,如果没有component的头结点,就把当前结点当作一个component的头结点,如果有就继续遍历。如果当前结点不在G中的话,说明前面的component已经结束,把father清空。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     int numComponents(ListNode* head, vector<int>& G) {
    12         if (!head) {return 0;}
    13         set<int> st(G.begin(), G.end());
    14         int cnt = 0;
    15         ListNode *cur = head, *father = nullptr;
    16         while (cur) {
    17             if (st.find(cur->val) == st.end()) {
    18                 father = nullptr;
    19             } else {
    20                 if (!father) {
    21                     father = cur;
    22                     cnt++;
    23                 } 
    24             }
    25             cur = cur->next;
    26         }
    27         return cnt;
    28     }
    29 };
    View Code

    【876】Middle of the Linked List 

  • 相关阅读:
    Excel公式进阶教程
    Excel公式初级教程
    一阶常系数线性差分方程通解求法
    博客园为代码块添加复制功能
    MFC分割窗口(CSplitterWnd)与选项卡视图(CTabView)的混合使用
    自制软件改变窗口大小
    conda的基本使用
    安装GPU驱动
    更换conda源、安装pytorch
    服务器安装anaconda
  • 原文地址:https://www.cnblogs.com/zhangwanying/p/9797184.html
Copyright © 2011-2022 走看看