Problem link:
http://oj.leetcode.com/problems/reorder-list/
I think this problem should be a difficult problem, since it requries three classic algorithms on the single-linked list:
- Split a single-linked list into halves
- Reverse a single-linked list
- Combine two single-linked list into one alternately
Split a single-linked list into havles
The technique of Fast/Slow pointers is commonly used in the single-linked list problems.
Initially, let F and S both be the head of the list. Then each iteration, S goes one step and F goes two steps. The iteration is terminate when F touch the end of the list.
Then, S should be points to the first element of the second half of the list.
Reverse a sinigle-linked list
To reverse a single-linked list in O(n) time, we need scan the list from the second element. For each element, lets say E, we need insert it in the front of head and update the head as E. Because, the insertion may set E->next to the old head, we need an extra pointer to keep track the element after E. Do not forget to set the orginal first (the last after reversing) element's next to NULL (or set it at the begining).
Combine two single-linked list into one alternately
We need three pointers, one used to keep track the combined list, the other two pointers are used for keep the first uncombined element of two lists.
The C++ code is as follows.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode *head) {
ListNode * h1 = head;
ListNode * h2 = head;
ListNode * p1 = NULL;
ListNode * p2 = NULL;
ListNode * p = head;
// Special case: len=0, len=1, len=2
for (int i=0; i<3; i++) {
if (p == NULL) return;
p = p->next;
}
// Step 1: split the list into halves
while (h1 != NULL) {
h2 = h2->next;
h1 = h1->next;
if (h1 != NULL) h1 = h1->next;
}
// now h2 is the head of the second half
// Step 2: Reverse h2, h2 could not be NULL for len >= 2
p2 = h2->next;
// The head should be the last element after reversing
h2->next = NULL;
// Each time, we move the element of p2 in the front of head
while(p2 != NULL) {
p = p2->next; // Record the next element
p2->next = h2; // Insert p2 in fornt of h2
h2 = p2; // New head is p2
p2 = p; // Go on the next element
}
// Step 3: combine h1 and h2
// The first element is always the first
h1 = head->next;
// each time we fill p->next with h1 or h2
p = head;
// Because we know that len(h1) = len(h2) or len(h1) = len(h2) + 1
// so after picking one element from the first half,
// the length of the second half should be not shorter than the first half
// It is sufficient to terminate the combination when p2 is NULL
while(h2 != NULL) {
p->next = h2;
h2 = h2->next;
p = p->next;
if (h1 != NULL) {
p->next = h1;
h1 = h1->next;
p = p->next;
}
}
p->next = NULL;
}
};
浙公网安备 33010602011771号