题目如下 :
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}
.
第一种思路(时间超时):
先将链表最后一个元素插入新表末尾,再将第一元素插入表末尾!代码如下。时间超时,因为每次找最后一个元素,都需要遍历整个链表。
void reorderListTimeLimit(ListNode *head) {
if (NULL == head) return;
ListNode *first = head->next,*tail=NULL,*pre=NULL,*last=NULL;
head->next = NULL;
tail = head;
while (NULL != first)
{
pre = first;
last = first;
while (NULL != last->next){ pre = last; last = last->next; }
if (pre != last) pre->next = NULL;
tail->next = last;
tail = tail->next;
tail->next = NULL;
if (first == NULL) break;
ListNode *t = first;
first = first->next;
tail->next = t;
tail = tail->next;
tail->next = NULL;
}
while (head)
{
cout << head->val << endl;
head = head->next;
}
}
第二种思路(通过):
仔细观察重新排序后的链表,发现链表是在前面链表的一半元素中间倒序插入链表后面一半元素。所以,首先找到中间元素,将中间元素以后的所有节点依次放入栈内。然后栈每弹出一个元素,将该元素插入前面元素的中间。
比如说链表1,2,3,4,5,6 首先找出中间节点4,将4后面的节点依次压入栈。此时栈中元素为5,6 且6为栈顶元素。
然后将栈顶弹出,此时为6,插入1与2中间。接着弹出下一个元素,插入2与3中间。直到栈为空。
代码如下:
找出中间节点
ListNode *getmid(ListNode *head)
{
ListNode *slow, *fast;
slow = head;
fast = head;
while (fast!=NULL && fast->next!=NULL)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
void reorderList(ListNode *head) {
if (NULL == head) return;
stack<ListNode*> s;
ListNode *middle = getmid(head);
ListNode *work = NULL;//工作节点
work = middle;
while (work->next != NULL)
{
s.push(work->next);
work = work->next;
}
middle->next = NULL;
while (!s.empty())
{
work = s.top();
work->next = head->next;
head->next = work;
head = head->next->next;
s.pop();
}
}重排
void reorderList(ListNode *head)
{
if (NULL == head) return;
stack<ListNode*> s;
ListNode *middle = getmid(head);
ListNode *work = NULL;//工作节点
work = middle;
while (work->next != NULL)
{
s.push(work->next);
work = work->next;
}
middle->next = NULL;
while (!s.empty())
{
work = s.top();
work->next = head->next;
head->next = work;
head = head->next->next;
s.pop();
}
}