【2】Add Two Numbers (2018年11月30日,第一次review,ko)node
兩個鏈表,表明兩個整數的逆序,返回一個鏈表,表明兩個整數相加和的逆序。算法
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 };
【19】Remove Nth Node From End of List (2018年10月30日 算法羣)數組
給了一個鏈表,從尾部刪除第 N 個結點。dom
題解:two pointers,fast 先走 N 步,而後slow,fast 一塊兒走,fast走到最後一個非空結點,slow就走到了要刪除結點的前一個結點。(注意有個特判狀況是若是第N個結點是頭節點,那麼要特殊處理)ide
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 };
【21】Merge Two Sorted Lists 函數
合併兩個有序鏈表變成一個大鏈表,大鏈表要求有序。(歸併排序)spa
題解:無,直接歸併3d
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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
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 };
【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 };
【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 };
【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, \root.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 };
【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 };
【876】Middle of the Linked List