[LeetCode题解]143. 重排链表 | 快慢指针 + 反转

解题思路

找到右边链表,再反转右边链表,然后按左、右逐一合并

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int val=0, ListNode next=null) {
 *         this.val = val;
 *         this.next = next;
 *     }
 * }
 */
public class Solution {
    public void ReorderList(ListNode head) {
        // 找到右边链表,再反转,然后逐一合并
        if(head == null || head.next == null) {
            return;
        } 

        // 找到右边链表
        ListNode fast = head, slow = head;
        while(fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }

        ListNode rightHead = slow.next;
        slow.next = null;   // 拆分左右两链表

        ListNode left = head;
        ListNode right = Reverse(rightHead);    // 反转右边链表

        // 使用虚拟头,按左、右逐一合并
        ListNode dummy = new ListNode();
        ListNode cur = dummy;
        while(left != null && right != null) {
            cur.next = left;
            cur = cur.next;
            left = left.next;

            cur.next = right;
            cur = cur.next;
            right = right.next;
        }

        cur.next = left != null ? left : right;

        head = dummy.next;  // 最后把 head 指向新的链表的头
    }

    private ListNode Reverse(ListNode head) {
        ListNode cur = head, pre = null;
        while(cur != null) {
            var nextTmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nextTmp;
        }

        return pre;
    }
}

复杂度分析

  • 时间复杂度:\(O(n)\),其中 \(n\) 是链表长度。相当于进行了两次遍历,因此时间复杂度为 \(O(n)\)
  • 空间复杂度:\(O(1)\)。只使用了几个节点指针。
posted @ 2020-11-21 16:09  大杂草  阅读(200)  评论(0编辑  收藏  举报