给定一个单链表 L 的头节点 head ,单链表 L 表示为:L0 → L1 → … → Ln - 1 → Ln请将其重新排列后变为:L0 → Ln → L1 → Ln - 1

力扣原题:

 先贴代码:

public class Solution143 {
    public void reorderList(ListNode head) {
        //找到原链表的中间节点
        ListNode mid = middleNode(head);
        //将原链表中点之后的链表反转逆置,再返回反转后的头节点
        ListNode last = Reverse(mid);
        //使中点的next域为空,断开链表
        mid.next = null;
        //将链表的前半部分和反转后的后半部分合并
        merge(head,last);
    }
    public ListNode middleNode(ListNode head){
        //寻找链表中点的方法为快慢指针法
        ListNode slow = head;
        ListNode fast = head;
        //快指针每次走两步,慢指针每次走一步,等快指针到终点的时候慢指针正好在链表的中间位置
        while (fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        //返回慢指针所在的节点,即为中间节点
        return slow;
    }
    public ListNode Reverse(ListNode mid){
        //将中点之后的链表进行反转,使后一个节点指向前一个节点
        ListNode cur = mid.next;
        ListNode tmp = mid; //为了避免混淆,新建一个tmp节点替代mid进入循环
        while (cur != null){
            ListNode ret = cur.next;
            cur.next = tmp;
            tmp = cur;
            cur = ret;
        }
        return tmp;
    }
    public void merge(ListNode l1 ,ListNode l2){
        //最后进行合并操作,若原链表为奇数情况则l1和l2相遇时循环结束;
        //  偶数情况则是l2的next域为null时循环结束
        while (l1 != l2 && l2.next != null){
            ListNode cur = l1.next;
            ListNode tmp = l2.next;
            l1.next = l2;
            l2.next = cur;
            l2 = tmp;
            l1 = cur;
        }
    }
}

思路解析: 

题目中要求我们将链表按照一定顺序重新排列,如下图演示,意思就是将倒数第一个排在第一个后面,倒数第二个排在第二个后面,依此类推。

 由上图我们可以看到,原来链表的中间节点经重新排列后变成了最后一个节点,通过这点我们便可以从中间节点入手来解决问题。

因为单链表只能指向它的后继节点无法指向前驱节点,所以直接将最后一个节点排在第一个后面后,我们无法再对倒数第二个节点进行操作;必须先将原链表分为两个部分,把后半部分的链表再进行反转逆置操作,这样原来链表的最后一个节点就变成了后半部分链表的头节点,最后把前半部分链表和后半部分链表再来一个合并操作(按题目里的排列顺序合并),就可以解决问题了!

猜你喜欢

转载自blog.csdn.net/weixin_56960711/article/details/122435301