Reorder List

Apr 25, 2016


Patching Array

题目描述

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}.

解法

代码如下:

public static void reorderList( ListNode head ) {
    if( head == null || head.next == null )
        return;
    ListNode slow = head, fast = head.next;
    while( fast != null && fast.next != null ) {
        slow = slow.next;
        fast = fast.next.next;
    }
    ListNode h1 = head, h2 = reverseList( slow.next );
    slow.next = null;
    while( h2 != null ) {
        ListNode h2next = h2.next;
        h2.next = h1.next;
        h1.next = h2;
        h1 = h2.next;
        h2 = h2next;
    }
}
private static ListNode reverseList( ListNode head ) {
    ListNode pre = null, curr = head;
    while( curr != null ) {
        ListNode next = curr.next;
        curr.next = pre;
        pre = curr;
        curr = next;
    }
    return pre;
}

思考过程:

首先考虑节点个数为奇偶的情况:

  • 节点个数为奇数 : 链表右半段插入左半段, 例如{1, 2, 3} => {1, 3, 2}
  • 节点个数为偶数 : 链表右半段插入左半段, 例如{1, 2, 3, 4} => {1, 4, 2, 3}

也就是说, 无论节点个数为奇偶, 算法是一样的, 没有额外的边界情况. 但是注意平分左右半段的时候, 如果多出一个节点要归到左半段, 而使用快慢指针恰好满足这种情况.

算法处理流程流程如下:

  • 使用快慢指针找到切分点, 把链表切成左半段和右半段
  • 翻转右半段
  • 把右半段插入左半段

时空复杂度: 时间复杂度是O(n), 空间复杂度是O(1)


上一篇博客:Patching Array
下一篇博客:Add Digits