题解 | #重排链表#

重排链表

https://www.nowcoder.com/practice/3d281dc0b3704347846a110bf561ef6b

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public void reorderList(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) return;
        // 重排为:0, n, 1, n-1, 2, n-2
        /*
          解题思路:
            1.先使用快慢指针,找到链表的中间节点
            2.将后半部分的链表反转(双指针局部反转)
            3.将两个链表合并
         */
        // 1.快慢指针找到中间节点
        ListNode fast = head, slow = head;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode midHead = slow.next; // 下半部分的头节点
        slow.next = null; // 释放节点
        // 2.反转后半部分链表
        midHead = reverseList(midHead); // 个数少于前半部分或等于前半部分
        // 3.链表合并
        while (midHead != null) {
            ListNode temp = midHead.next;
            midHead.next = head.next;
            head.next = midHead;
            head = midHead.next;
            midHead = temp;
        }
    }
    // 链表反转
    private ListNode reverseList(ListNode head) {
        if (head == null) return null;
        ListNode tail = head;
        head = head.next;
        tail.next = null; // 链表(尾部)头部指向 null
        while (head != null) {
            ListNode temp = head.next;
            head.next = tail; // 指针反转
            // 都向前走一个节点
            tail = head;
            head = temp;
        }
        return tail;
    }
}

可以先使用快慢指针找到中间节点,然后将后半部分的链表通过双指针迭代进行反转,最后将两部分链表进行合并即可。

时间复杂度O(N):N表示链表长度,双指针一次遍历

空间复杂度O(1):常数大小空间指针

全部评论

相关推荐

点赞 评论 收藏
分享
11-07 13:31
怀化学院 Java
勇敢牛牛不怕难:又疯一个
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务