首页 > 代码库 > 第11题 Reorder List

第11题 Reorder List

Given a singly linked list LL0L1→…→Ln-1Ln,
reorder it to: L0LnL1Ln-1L2Ln-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}.

Solution1:用stack解题

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public void reorderList(ListNode head) {
        if(head==null || head.next ==null ||head.next.next==null) return;
      
        ListNode current = head;
        Stack<ListNode> tails = new Stack<ListNode>();
        int length =0;
        while(current!=null){
            tails.push(current);
            current=current.next;
            length++;
        }
        current = head;
        for(int position=0; position<length-2; position+=2){
            ListNode tail = tails.pop();
            tail.next = current.next;
            current.next = tail;
            current = current.next.next;
        }
        if(length%2!=0)   current.next=null;
        else current.next.next=null;
        
        return;
    }
}


Solution2:第一步,找到list的中点(用两个步长为1和2的指针实现);第二步,讲list后半部分翻转;第三步,讲list前后部分合并。这种方法不用记录长度为奇数或偶数。

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public void reorderList(ListNode head) {
        if(head==null || head.next ==null ||head.next.next==null) return;
      
        ListNode tail=head, mid=head;
        while(tail.next!=null && tail.next.next!=null){
            tail=tail.next.next;
            mid=mid.next;
        }
        //reverse the nodes after mid, produce 2 lists, first half list and second half list
        tail = mid.next;   //the tail of second half list is tail
        mid.next = null;    //first list from head to mid
        ListNode prev=null, next;
        while(tail!=null){//reverse list
                next = tail.next;
                tail.next = prev;
                prev = tail;
                if(next!=null)
                    tail=next;
                else
                    break;
        }
        //now tail is the head for the second half
        //merge two lists
        while(tail!=null){//use tail!=null because list started from tail is always shorter than list started from head
            next = tail.next;
            tail.next = head.next;
            head.next = tail;
            tail= next;
            head = head.next.next;
            
        }
        
        return;
    }
}
注意翻转list的操作里当next==null时表示遍历到原list尾,即翻转list的头部,则不执行tail=next操作,否则tail会指向null,丢失翻转list的头部。

两种方法执行前都要判断head或head.next或head.next.next是否为null,因为此方法要求list中至少有三个元素,否则可直接返回。



第11题 Reorder List