143. Reorder List(重新排序链表)

题目描述

Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…

You may not modify the values in the list’s nodes, only nodes itself may be changed.

Example 1:

Given 1->2->3->4, reorder it to 1->4->2->3.

Example 2:

Given 1->2->3->4->5, reorder it to 1->5->2->4->3.

Approach1:

class Solution {
    //Runtime: 2 ms, faster than 99.31% of Java 
    //Memory Usage: 39 MB, less than 89.97% of Java 
    public void reorderList(ListNode head) {
      if (head == null || head.next == null)
          return;
      // step 1. cut the list to two halves
      ListNode prev = null, slow = head, fast = head, l1 = head;
      while (fast != null && fast.next != null) {
        prev = slow;      // prev will be the tail of 1st half
        slow = slow.next; // slow will be the head of 2nd half
        fast = fast.next.next;
      }
      prev.next = null;
      
      // step 2. reverse the 2nd half
      ListNode l2 = reverse(slow);
      
      // step 3. merge the two halves
      merge(l1, l2);
    }
    
    public ListNode reverse(ListNode head) {
      ListNode prev = null, curr = head, next = null;
      
      while (curr != null) {
        next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
      }
      
      return prev;
    }
    
    void merge(ListNode l1, ListNode l2) {
      while (l1 != null) {
        //画图会更加清楚易懂
        ListNode n1 = l1.next, n2 = l2.next;
        //n1 、 n2 分别是l1 、 l2指向的下一个结点
        l1.next = l2;
        if (n1 == null)
          break;
        l2.next = n1;
        l1 = n1;//进入下一次的迭代
        l2 = n2;
      }
    }

  }

另一种形式方便理解:

class Solution {
    //Runtime: 2 ms, faster than 99.31% of Java 
    //Memory Usage: 39 MB, less than 89.97% of Java 
    public void reorderList(ListNode head) {
      if (head == null || head.next == null)
          return;
      // step 1. cut the list to two halves
      ListNode prev = null, slow = head, fast = head, l1 = head;
      while (fast != null && fast.next != null) {
        prev = slow;      // prev will be the tail of 1st half
        slow = slow.next; // slow will be the head of 2nd half
        fast = fast.next.next;
      }
      prev.next = null;
      
      // step 2. reverse the 2nd half
      ListNode l2 = reverse(slow);
      
      // step 3. merge the two halves
      head = merge(l1, l2);
    }
    
    public ListNode reverse(ListNode head) {
      ListNode prev = null, curr = head, next = null;
      
      while (curr != null) {
        next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
      }
      
      return prev;
    }
    
    public ListNode merge(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(0);
        ListNode handler = head;
        while(l1 != null){
            handler.next = l1;
            l1 = l1.next;
            handler = handler.next;
            handler.next = l2;
            l2 = l2.next;
            handler = handler.next;
        }
        if(l2 != null)
            handler.next = l2;
        return head.next;
    }

  }

Approach2:

class Solution{
    //Runtime: 2 ms, faster than 99.31% of Java
    //Memory Usage: 40.3 MB, less than 29.17% of Java
    public void reorderList(ListNode head) {
            if(head==null||head.next==null) return;
            
            //Find the middle of the list
            ListNode p1=head;
            ListNode p2=head;
            while(p2.next!=null&&p2.next.next!=null){ 
                p1=p1.next;
                p2=p2.next.next;
            }
            
            //Reverse the half after middle  1->2->3->4->5->6 to 1->2->3->6->5->4
            ListNode preMiddle=p1;
            ListNode preCurrent=p1.next;
            while(preCurrent.next!=null){
                ListNode current=preCurrent.next;
                preCurrent.next=current.next;
                current.next=preMiddle.next;
                preMiddle.next=current;
            }
            
            //Start reorder one by one  1->2->3->6->5->4 to 1->6->2->5->3->4
            p1=head;
            p2=preMiddle.next;
            while(p1!=preMiddle){
                preMiddle.next=p2.next;
                p2.next=p1.next;
                p1.next=p2;
                p1=p2.next;
                p2=preMiddle.next;
            }
        }
}

猜你喜欢

转载自blog.csdn.net/IPOC_BUPT/article/details/88032963