- 描述
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}.
- 思路
比较容易想到的思路就是循环遍历链表,找到最后一个节点,将最后一个节点插到第一个节点,由于每次都要遍历链表,因此该算法的时间复杂度为nlogn,空间复杂度为1。下面给出代码 - 代码(c#)
public void ReorderList(ListNode head)
{
if (head == null) return;
while (head.next != null && head.next.next != null)
{
var next = head.next;//保存下个节点
var last = GetLast(head);//得到最后一个节点,使最后一个节点的前一个节点赋值为null
head.next = last;//插入节点
last.next = next;//插入节点
head = next;
}
}
public ListNode GetLast(ListNode head)
{
while (head.next.next != null)
{
head = head.next;
}
var r = head.next;
head.next = null;
return r;
}
- 优化
以上代码虽然能ac,但是效率较低,参考了其他博主的思路,发现这道题目可以使用快慢指针的方式解决。分三步,
1、将链表分为前后两个部分。
2、将后面的链表进行反转。
3.、将两个链表合并。
下面给出代码 - 代码(c#)
public void ReorderList(ListNode head)
{
if (head == null||head.next==null) return;
var slow = head;
var fast = head;
while ( fast.next != null&&fast.next.next!=null)//将链表分为前后两个部分
{
slow = slow.next;
fast = fast.next.next;
}
fast = slow.next;
slow.next = null;
var p = fast;
var q = fast.next;
fast.next = null;
while (q != null)//将后面的链表反转
{
var temp = q.next;
q.next = p;
p = q;
q = temp;
}
q = p;
p = head;
while (p != null && q != null)//将两个链表合并
{
var temp1 = p.next;
var temp2 = q.next;
p.next = q;
q.next = temp1;
q = temp2;
p = temp1;
}
}
- 总结
在对链表进行一些操作的时候,可以考虑使用快慢指针的方式。 - 相关链接
参考博客:http://blog.csdn.net/qq508618087/article/details/50480251
原题链接:https://leetcode.com/problems/reorder-list/description/