leetcode — reorder-list

本文介绍了一种链表重排序算法的实现方法,通过寻找链表的中间节点,反转后半部分链表,并将其依次插入前半部分链表的每个元素后方。文章详细解释了算法步骤,并提供了完整的Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**
 * Source : https://oj.leetcode.com/problems/reorder-list/
 *
 * Given a singly linked list L: L0→L1→…→Ln-1→Ln,
 * reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
 *
 * You must do this in-place without altering the nodes' values.
 *
 * For example,
 * Given {1,2,3,4}, reorder it to {1,4,2,3}.
 */
public class RecordList {


    /**
     * 将链表的后半部分翻转之后依次插入链表前半部分每个元素后面
     *
     * 设链表长度为n
     * 1. 找到链表后半部分起始位置: n/2+1,使用双指针法,slow每次移动一个,fast每次移动两个,fast移动到最后的时候,slow指向的正好是 n/2+1
     * 2. 反转后半部分连链表
     * 3. 将反转后的后半部分链表依次插入前半部分,left指向左边,right指向反转后的第一个node,依次插入left的后一个,直到right指向null,
     *      right每次移动一个node,left每次移动2个node(因为刚刚left后面插入一个节点)
     *
     * @param head
     * @return
     */
    public LinkedNode record (LinkedNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        LinkedNode midNode = findMidNode(head);
        LinkedNode reversedList = reverse(midNode);
        LinkedNode left = head;
        LinkedNode right = reversedList;

        while (right != null && right.next != null) {
            // 记录将要被插入的元素
            LinkedNode target = right;
            // 下一个需要被插入的元素
            right = right.next;
            // 插入target到链表中
            target.next = left.next;
            left.next = target;
            left = left.next.next;
        }

        return head;
    }


    private LinkedNode findMidNode (LinkedNode head) {
        LinkedNode slow = head;
        LinkedNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }


    private LinkedNode reverse (LinkedNode head) {
        LinkedNode p = head;
        LinkedNode pre = null;
        while (p != null) {
            LinkedNode next = p.next;
            p.next = pre;
            pre = p;
            p = next;
        }
        return pre;
    }

    private class LinkedNode {
        int value;
        LinkedNode next;

    }

    /**
     * 创建普通的链表
     * @param arr
     * @return
     */
    public LinkedNode createList (int[] arr) {
        if (arr.length == 0) {
            return null;
        }
        LinkedNode head = new LinkedNode();
        head.value = arr[0];
        LinkedNode pointer = head;
        for (int i = 1; i < arr.length; i++) {
            LinkedNode node = new LinkedNode();
            node.value = arr[i];
            pointer.next = node;
            pointer = pointer.next;
        }
        return head;
    }

    private static void print (LinkedNode head) {
        if (head == null) {
            System.out.println("[]");
        }
        StringBuffer stringBuffer = new StringBuffer("[");
        while (head != null) {
            stringBuffer.append(head.value);
            stringBuffer.append(",");
            head = head.next;
        }
        stringBuffer.deleteCharAt(stringBuffer.length()-1);
        stringBuffer.append("]");
        System.out.println(stringBuffer);
    }


    public static void main(String[] args) {
        RecordList recordList = new RecordList();
        int[] arr = new int[]{1,2,3,4,5,6};
        print(recordList.record(recordList.createList(arr)));

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值