您的位置:首页 > 其它

Leetcode:Reorder List 单链表重排序

2014-04-28 18:37 411 查看
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}
.

分析:观察重排前和重排后的序列,发现单链表前半部分各元素的相对顺序保持不变,而后半部分逆序。因此可将单链表一分为二,分成两个子链表;然后将后半部分子链表逆序;然后交叉合并这两个子链表得到结果链表。因此这个问题可分为三个子问题:

1)找出单链表的中间节点,以便将单链表一分为二;

2)将单链表后半部分逆置;

3)交叉合并两个子链表。

代码如下:

class Solution {
public:
//返回单链表的中间节点
ListNode *findMidNode(ListNode *head)
{
if(head == NULL)return NULL;
ListNode *fast = head;
ListNode *slow = head;
while(fast->next && fast->next->next)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
//单链表逆序
ListNode *reverse(ListNode *head)
{
if(head == NULL)return NULL;
ListNode *tail = NULL;
ListNode *nxt = NULL;
while(head != NULL)
{
nxt = head->next;
head->next = tail;
tail = head;
head = nxt;
}
return tail;
}
//交叉合并两个单链表
ListNode *crossMerge(ListNode *head1,ListNode *head2)
{
if(head1 == NULL)return NULL;
if(head2 == NULL)return NULL;
//设置辅助头结点,可在第一次插入节点时避免判断是否是头结点
ListNode dummy(0);
ListNode *tail = &dummy;
ListNode *p = head1;
ListNode *q = head2;
while(p && q)
{
tail->next = p;
tail = p;
p = p->next;
tail ->next = q;
tail = q;
q = q->next;
}
if(p)
tail->next = p;
if(q)
tail->next = q;

return dummy.next;
}

void reorderList(ListNode *head)
{
if(head == NULL || head->next == NULL)return;
ListNode *mid_node = findMidNode(head);
ListNode *head2 = mid_node->next;
head2 = reverse(head2);
mid_node->next = NULL;
head = crossMerge(head,head2);
return;
}
};


总结+牢骚:我觉得无论单链表的问题如何改变,差不多都可以将其划分为若干个基本子问题。这道题就是一个很典型的栗子。在找工作之前有必要把leetcode上关于单链表的题目多刷几遍!!!刷完题之后就写个leetcode单链表题目的总结吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: