题目
给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2:
给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.
解答
解法一
具体步骤如下:
- 使用快慢指针找到中心点。(中心点需要是左边界)
- 翻转后半部分链表。(非递归翻转)
- 将前半部分链表和翻转后的后半部分链表交错链接。
更详细内容请看代码注释。
复杂度:O(n) 的时间,O(1) 的空间
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public void reorderList(ListNode head) {
if(head == null || head.next == null) return;
// 找中心点
ListNode slow = head;
// 初始化为 head.next 是为了找到中心点左边界
// 目的是让 slow 无论链表总数是奇/偶都指向后半段的前驱结点。
ListNode fast = head.next;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 翻转后半部分链表
ListNode pre = slow;
ListNode cur = pre.next.next;
pre.next.next = null;
while(cur != null) {
ListNode next = cur.next;
cur.next = pre.next;
pre.next = cur;
cur = next;
}
// 取得翻转后的右部分链表,并与原链表断开
ListNode right = slow.next;
slow.next = null;
// 链接两个链表
ListNode p = head;
while(p != null && right != null) {
ListNode rNext = right.next;
ListNode pNext = p.next;
right.next = p.next;
p.next = right;
right = rNext;
p = pNext;
}
}
}
结果
解法二
具体步骤如下:
- 使用快慢指针找到中心点。(中心点需要是左边界)
- 翻转后半部分链表。(递归翻转)
- 将前半部分链表和翻转后的后半部分链表交错链接。
更详细内容请看代码注释。
复杂度:O(n) 的时间,O(1) 的空间
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public void reorderList(ListNode head) {
if(head == null || head.next == null) return;
// 找中心点
ListNode slow = head;
// 初始化为 head.next 是为了找到中心点左边界
// 目的是让 slow 无论链表总数是奇/偶都指向后半段的前驱结点。
ListNode fast = head.next;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 取得翻转后的右部分链表,并与原链表断开
ListNode right = reverseList(slow.next);
slow.next = null;
// 链接两个链表
ListNode p = head;
while(p != null && right != null) {
ListNode rNext = right.next;
ListNode pNext = p.next;
right.next = p.next;
p.next = right;
right = rNext;
p = pNext;
}
}
private ListNode reverseList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}