剑指 Offer II 026. 重排链表

65 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

一、题目描述:

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

 L0 → L1 → … → Ln-1 → Ln  请将其重新排列后变为:

L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

 

示例 1:

image.png

输入: head = [1,2,3,4] 输出: [1,4,2,3] 示例 2:

image.png

输入: head = [1,2,3,4,5] 输出: [1,5,2,4,3]  

提示:

链表的长度范围为 [1, 5 * 104] 1 <= node.val <= 1000  

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/LG…

二、思路分析:

遍历链表,将每个结点依次加入数组,则数组中的结点顺序和原始链表的结点顺序相同。根据重新排列的规则,需要将原始链表的结点按照从外到内的顺序连接,因此可以定义两个下标 slow 和 fast 分别指向首尾的待连接的结点,初始时slow 和 fast 分别为头结点和尾结点的下标。
具体解题过程:
使用快慢指针,快指针一次走两步,慢指针一次走一步,当快指针走到链表尾节点时慢指针刚好走到链表的中间节点
反转链表的后半段
将两个链表依次相链

三、AC 代码:

class Solution {
    public void reorderList(ListNode head) {
        ListNode mid = findMid(head);
        ListNode curA = head;
        ListNode curB = reverse(mid.next);
        mid.next = null;
        merge(curA, curB);
    }
    private ListNode findMid(ListNode head){
        ListNode tmp = new ListNode(0);
        tmp.next = head;
        ListNode slow = tmp, fast = tmp;
        while (fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    private ListNode reverse(ListNode head){
        ListNode reversedList = null;
        while (head != null){
            ListNode next = head.next;
            head.next = reversedList;
            reversedList = head;
            head = next;
        }
        return reversedList;
    }
    private ListNode merge(ListNode l1, ListNode l2){
        int flag = 1;
        ListNode head = new ListNode(0);
        while (l1 != null || l2 != null){
            if (flag % 2 == 0){
                head.next = l2;
                l2 = l2.next;
            }else{
                head.next = l1;
                l1 = l1.next;
            }
            flag++;
            head = head.next;
        }
        return head.next;
    }
}

四、总结:

image.png 掘友们,解题不易,如果觉得有用就留下个赞或评论再走吧!谢啦~ 💐