Leet Code 143:Reorder List 对一个链表重新排序

问题: Given a singly linked list  L L 0 L 1 →…→ L n-1 L n ,

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

题解:对于一个链表L,L0L1→…→Ln-1Ln,对它进行重新排序,重新排序后的结果为L0LnL1Ln-1L2Ln-2→…,即最后一个插在第一个后面,倒数第二个插在第二个后面,倒数第三个插在第三个后面,。。。。     注意题目有个要求,你不能通过替换链表节点值的方式解决此问题

分析:我想有些人对这个问题应该比较熟悉,对于一个链表L,L0L1→…→Ln-1Ln,对它进行重新排序,排序后的结果

L0L(n/2+1)L1L(n/2+2)L2L(n/2+3)→…,即链表分为两部分,左边的长度-右边的长度<=1(链表长度偶数时,左右相等,奇数时左边多一个节

点)。右边第一个插在左边第一个后面,右边第二个插在左边第二个后面,右边第三个,插在左边第三个后面。。。

For example,

Given{1,2,3,4},reorder it to{1,3,2,4}

显然,解决这个问题分为两步

第一步,找到链表的中间位置

第二步,将右半部分插入左半部分

但是这个LeetCode问题中,对右半部分的插入顺序刚好与上述问题的插入顺序逆序,我们很自然的可以想到,在执行插入操作之前,应该有一个逆序操作,所以解决这个问题就分为了三步。

第一步,找到链表的中间位置

第二步,将右半部份做逆序调整

第三部,将右半部份插入到左半部分

以下是代码:

public void reorderList(ListNode head) {
            if(head==null||head.next==null) return;
            
            //第一步,找到链表中间位置
            ListNode p1=head;
            ListNode p2=head;
            while(p2.next!=null&&p2.next.next!=null){ 
                p1=p1.next;
                p2=p2.next.next;
            }
            
            //对右半部份执行逆序操作  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;
            }
            
            //将右半部份插入到左半部分  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/VP_19951105/article/details/70131716