2014-05-12 06:56
原题:
A link list contains following elements struct node{ int data; node* next; node* random; } Given head of such a linked list write a function who copies such a linked list and returns the head of the new list. So if in the original list first node points to fourth node in random the copy should have the same relation. The random pointer can point to any node including itself and more than two nodes can have random pointer to the same node. Required time complexity O(n) and no extra space can be used (apart from the newly allocated memory which you will need to create the new list)
题目:Leetcode上有这题,Copy List with Random Pointer。不过要求做到O(n)时间以及O(1)空间。
解法:之前我用了哈希表,能够实现O(n)时间,但不能做到O(1)空间。查阅了别人的解法后我发现自己的思路果然还不够灵活。这种解法很巧妙,先将新节点按照“旧->新->旧->新->旧->新”穿插到旧链表中,然后执行一条关键语句:ptr->next->random = ptr->random->next。执行完了以后将两条链表拆开即可(归并链表的逆过程)。哎,又是一个需要灵感才能想出的算法。
代码:
1 // http://www.careercup.com/question?id=5917873302142976 2 #include <iostream> 3 #include <unordered_map> 4 using namespace std; 5 6 struct ListNode { 7 int val; 8 ListNode *next; 9 ListNode*random; 10 ListNode(int _val = 0): val(_val), next(nullptr), random(nullptr) {}; 11 }; 12 13 class Solution { 14 public: 15 ListNode *copyListWithRandomPointer(ListNode *head) { 16 if (head == nullptr) { 17 return nullptr; 18 } 19 ListNode *new_head; 20 ListNode *p1, *p2; 21 22 p1 = head; 23 while (p1 != nullptr) { 24 p2 = new ListNode(p1->val); 25 p2->next = p1->next; 26 p1->next = p2; 27 p1 = p1->next->next; 28 } 29 30 p1 = head; 31 while (p1 != nullptr) { 32 p1->next->random = p1->random == nullptr ? nullptr : p1->random->next; 33 p1 = p1->next->next; 34 } 35 new_head = splitList(head); 36 37 return new_head; 38 }; 39 private: 40 ListNode *splitList(ListNode *head) { 41 ListNode *head1, *head2; 42 ListNode *ptr1, *ptr2; 43 44 // head1 is the original list. 45 head1 = ptr1 = nullptr; 46 // head2 is the new list. 47 head2 = ptr2 = nullptr; 48 while (true) { 49 if (head == nullptr) { 50 break; 51 } 52 if (head1 == nullptr) { 53 head1 = ptr1 = head; 54 } else { 55 ptr1->next = head; 56 ptr1 = ptr1->next; 57 } 58 head = head->next; 59 60 if (head == nullptr) { 61 break; 62 } 63 if (head2 == nullptr) { 64 head2 = ptr2 = head; 65 } else { 66 ptr2->next = head; 67 ptr2 = ptr2->next; 68 } 69 head = head->next; 70 } 71 72 return head2; 73 }; 74 }; 75 76 void deleteList(ListNode *&head) 77 { 78 ListNode *ptr; 79 80 ptr = head; 81 while (head != ptr) { 82 ptr = head; 83 head = head->next; 84 delete ptr; 85 } 86 } 87 88 int main() 89 { 90 int val; 91 int n; 92 int i; 93 ListNode *head1, *head2; 94 ListNode *ptr; 95 unordered_map<int, ListNode *> um; 96 Solution sol; 97 98 while (cin >> n && n > 0) { 99 head1 = head2 = nullptr; 100 for (i = 0; i < n; ++i) { 101 cin >> val; 102 if (head1 == nullptr) { 103 head1 = ptr = new ListNode(val); 104 } else { 105 ptr->next = new ListNode(val); 106 ptr = ptr->next; 107 } 108 um[i] = ptr; 109 } 110 111 ptr = head1; 112 for (i = 0; i < n; ++i) { 113 cin >> val; 114 if (val >= 0) { 115 ptr->random = um[val]; 116 } else { 117 ptr->random = nullptr; 118 } 119 ptr = ptr->next; 120 } 121 122 head2 = sol.copyListWithRandomPointer(head1); 123 ptr = head2; 124 while (ptr != nullptr) { 125 cout << ptr->val << ' '; 126 cout << (ptr->random != nullptr ? ptr->random->val : -1) << endl; 127 ptr = ptr->next; 128 } 129 130 deleteList(head1); 131 deleteList(head2); 132 } 133 134 return 0; 135 }