2014.1.13 22:07
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.
For example,
Given {1,2,3,4}
, reorder it to {1,4,2,3}
.
Solution1:
My solution for this problem is in three steps:
1. cut the list in two halves of equal length (maybe differ by 1).
2. reverse the latter one.
3. merge them in a crossing manner: 1->2->1->2->1->...
Time complexity is O(n), space complexity is O(1), where n is the number of nodes in the list.
Accepted code:
1 // 4CE, 1AC, if you're able to design the right algorithm with just one shot, why failed by 4 foolish CEs? 2 /** 3 * Definition for singly-linked list. 4 * struct ListNode { 5 * int val; 6 * ListNode *next; 7 * ListNode(int x) : val(x), next(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 void reorderList(ListNode *head) { 13 // IMPORTANT: Please reset any member data you declared, as 14 // the same Solution instance will be reused for each test case. 15 if(head == nullptr){ 16 // 1CE here, void function... 17 return; 18 } 19 20 int n, n1, n2; 21 // 1CE here, ListNode, not List... 22 ListNode *h1, *h2, *ptr; 23 24 h1 = head; 25 ptr = head; 26 n = 0; 27 while(ptr != nullptr){ 28 ++n; 29 ptr = ptr->next; 30 } 31 n1 = (n + 1) / 2; 32 n2 = n - n1; 33 ptr = head; 34 // 1CE here, declaration for $i missing 35 for(int i = 1; i < n1; ++i){ 36 ptr = ptr->next; 37 } 38 h2 = ptr->next; 39 ptr->next = nullptr; 40 h2 = reverseList(h2); 41 42 ListNode *root = new ListNode(0), *tail; 43 ListNode *p1, *p2; 44 tail = root; 45 while(h1 != nullptr || h2 != nullptr){ 46 if(h1 != nullptr){ 47 tail->next = h1; 48 h1 = h1->next; 49 tail = tail->next; 50 tail->next = nullptr; 51 } 52 if(h2 != nullptr){ 53 tail->next = h2; 54 h2 = h2->next; 55 tail = tail->next; 56 tail->next = nullptr; 57 } 58 } 59 60 head = root->next; 61 delete root; 62 // 1CE here, void function has no return 63 } 64 private: 65 ListNode *reverseList(ListNode *head) { 66 if(nullptr == head){ 67 return head; 68 } 69 70 ListNode *ptr1, *ptr2, *root; 71 72 root = new ListNode(0); 73 ptr1 = head; 74 while(ptr1 != nullptr){ 75 ptr2 = root->next; 76 root->next = ptr1; 77 ptr1 = ptr1->next; 78 root->next->next = ptr2; 79 } 80 81 head = root->next; 82 delete root; 83 return head; 84 } 85 };
Solution2:
I've noticed that I used an extra new operation in the code. This overhead can be avoided.
Accepted code:
1 // 2WA, 1AC, not so satisfactory 2 class Solution { 3 public: 4 void reorderList(ListNode *head) { 5 if(head == nullptr){ 6 return; 7 } 8 9 int n, n1, n2; 10 ListNode *h1, *h2, *ptr; 11 12 h1 = head; 13 ptr = head; 14 n = 0; 15 while(ptr != nullptr){ 16 ++n; 17 ptr = ptr->next; 18 } 19 n1 = (n + 1) / 2; 20 n2 = n - n1; 21 ptr = head; 22 for(int i = 1; i < n1; ++i){ 23 ptr = ptr->next; 24 } 25 h2 = ptr->next; 26 ptr->next = nullptr; 27 h2 = reverseList(h2); 28 29 ListNode *tail; 30 ListNode *p1, *p2; 31 tail = nullptr; 32 head = h1; 33 while(h1 != nullptr || h2 != nullptr){ 34 if(h1 != nullptr){ 35 if(tail != nullptr){ 36 tail->next = h1; 37 tail = tail->next; 38 }else{ 39 tail = h1; 40 } 41 h1 = h1->next; 42 tail->next = nullptr; 43 } 44 if(h2 != nullptr){ 45 if(tail != nullptr){ 46 tail->next = h2; 47 tail = tail->next; 48 }else{ 49 tail = h2; 50 } 51 h2 = h2->next; 52 tail->next = nullptr; 53 } 54 } 55 } 56 private: 57 ListNode *reverseList(ListNode *head) { 58 if(nullptr == head){ 59 return head; 60 } 61 62 ListNode *ptr1, *ptr2; 63 64 ptr1 = head; 65 head = nullptr; 66 while(ptr1 != nullptr){ 67 ptr2 = ptr1; 68 ptr1 = ptr1->next; 69 if(head != nullptr){ 70 // 2WA here, better manually debug it before submission 71 ptr2->next = head; 72 head = ptr2; 73 }else{ 74 head = ptr2; 75 ptr2->next = nullptr; 76 } 77 } 78 79 return head; 80 } 81 };