【算法】【线性表】【链表】Reorder List 重排链表

1  题目

You are given the head of a singly linked-list. The list can be represented as:

L0 → L1 → … → Ln - 1 → Ln

Reorder the list to be on the following form:

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

You may not modify the values in the list's nodes. Only nodes themselves may be changed.

Example 1:

Input: head = [1,2,3,4]
Output: [1,4,2,3]

Example 2:

Input: head = [1,2,3,4,5]
Output: [1,5,2,4,3]

Constraints:

  • The number of nodes in the list is in the range [1, 5 * 104].
  • 1 <= Node.val <= 1000

2  解答

大致思路就是:先利用快慢指针找中间位置,然后将右边的链表反转,然后再左右遍历两个链表,将右边的挨个插入到左边的链表即可:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
class Solution {
    public void reorderList(ListNode head) {
        // 参数边界校验 节点为空  1个节点 2个节点 都可以直接返回
        if (head == null || head.next == null || head.next.next == null) {
            return;
        }
        // 先找到中间位置
        // 分别遍历两边链表
        // 将右边的节点依次插入左边的缝隙  (因为是单向链表,所以右边的链表先反转一下再遍历)
        // 1 2 3 4 5
        // 1 2 3 4
        // 快慢指针 寻找中间位置 slowNode 到达中间位置
        ListNode quickNode = head;
        ListNode slowNode = head;
        while (quickNode != null && quickNode.next != null) {
            quickNode = quickNode.next.next;
            // 说明下次循环要结束了 需要把当前的 slowNode 的 next 设置为空
            if (quickNode == null || quickNode.next == null) {
                ListNode temp = slowNode.next;
                slowNode.next = null;
                slowNode = temp;
            } else {
                slowNode = slowNode.next;
            }
        }
        // 对 slowNode 开始的节点进行反转
        // 还是老办法 加个头节点方便反转
        ListNode slowPreNode = new ListNode(0);
        slowPreNode.next = slowNode;
        ListNode node = slowNode;
        while (node != null) {
            ListNode nextNode= node.next;
            if (nextNode != null) {
                node.next = nextNode.next;
                nextNode.next = slowPreNode.next;
                slowPreNode.next = nextNode;
                continue;
            }
            node = node.next;
        }

        // 一个从 head 开始 一个从 slowPreNode.next 开始
        ListNode leftNode = head;
        ListNode rightNode = slowPreNode.next;

        // 左边的链表长度小于右边的 所以只要判断左边的链表不为空即可
        while (leftNode != null) {
            ListNode nextNode = leftNode.next;
            if (nextNode == null) {
                // 左边到了最后一个节点了,直接把右边的赋值(右边没遍历完的)给左边的next即可
                leftNode.next = rightNode;
                break;
            } else {
                // 右边的节点保留下
                node = rightNode;
                // 右边后移
                rightNode = rightNode.next;
                // 将 node 插入进来
                node.next = leftNode.next;
                leftNode.next = node;
                leftNode = node.next;
            }
        }
    }
}

加油。

posted @ 2024-01-18 07:18  酷酷-  阅读(3)  评论(0编辑  收藏  举报