LeetCode 143.重排链表

1.题目要求:将原链表重排序为:第一个节点->最后一个节点->第二个节点->倒数第二个节点->第三个节点->倒数第三个节点...。

2.思路:

以1->2->3->4->5为例。

(1)找到链表的中间节点middleNode:快慢指针法,找到中间节点mid = 3。

(2)翻转后半部分的链表reverseList:从中点开始反转后半部分的链表。反转后:1->2->3,5->4->3(注意3是共享节点)。

(3)交错合并:两个链表的节点从前往后逐个交错合并。

3.复杂度分析:

(1)时间复杂度:O(n),其中n为链表的长度。

(2)空间复杂度:O(1),仅用到若干额外变量。

4.疑问:循环条件while head2.next为什么不能写成while head2?(在hot100 234.回文链表中是while(head 2!=null),这里却是while(head2.next != null))

答:

这里不用head2 != null是为了防止形成环, 由于mid节点是重排链表后的最后一个节点,因此当head2刚走到mid时:

(1)要么此时head1也指向mid(此时对应于链表是奇数的情况)

(2)要么此时head1指向mid节点的前一个节点(对应于链表是偶数的情况)

无论哪种情况都表明这个链表已经在head2刚走到mid时重排完成,因此可以直接退出循环,再继续循环到head2 == null会形成环。

附代码:

java 复制代码
class Solution {
    public void reorderList(ListNode head) {
        ListNode mid = middleNode(head);
        ListNode head2 = reverseList(mid);
        // 这里不用head2 != null是为了防止形成环
        // 由于mid节点是重排链表后的最后一个节点
        // 因此当head2刚走到mid时
        // (1)要么此时head1也指向mid(此时对应于链表是奇数的情况)
        // (2)要么此时head1指向mid节点的前一个节点(对应于链表是偶数的情况)
        // 无论哪种情况都表明这个链表已经重排完成,因此可以直接退出循环,再继续循环下去会形成环
        while(head2.next != null){
            ListNode next1 = head.next;
            ListNode next2 = head2.next;
            head.next = head2;
            head2.next = next1;
            head = next1;
            head2 = next2;
        }
    }
    // 876.链表的中间节点,快慢指针法
    private ListNode middleNode(ListNode head){
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    // 206.反转链表
    private ListNode reverseList(ListNode head){
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}

ACM模式:

java 复制代码
import java.util.Scanner;

// 将 ListNode 定义为独立的类
class ListNode {
    int val;
    ListNode next;
    ListNode(int val) {
        this.val = val;
        this.next = null;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取链表长度
        int n = scanner.nextInt();

        // 读取链表元素
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) {
            nums[i] = scanner.nextInt();
        }

        // 创建链表
        ListNode head = null;
        if (n > 0) {
            head = new ListNode(nums[0]);
            ListNode current = head;
            for (int i = 1; i < n; i++) {
                current.next = new ListNode(nums[i]);
                current = current.next;
            }
        }

        // 调用重排链表方法
        Solution solution = new Solution();
        solution.reorderList(head);

        // 输出重排后的链表
        if (head == null) {
            System.out.println("");
        } else {
            ListNode current = head;
            while (current != null) {
                System.out.print(current.val);
                if (current.next != null) {
                    System.out.print(" ");
                }
                current = current.next;
            }
            System.out.println();
        }

        scanner.close();
    }
}

// 重排链表方法放在 Solution 类中
class Solution {
    public void reorderList(ListNode head) {
        if (head == null || head.next == null) {
            return;
        }

        ListNode mid = middleNode(head);
        ListNode head2 = reverseList(mid);

        while (head2.next != null) {
            ListNode next1 = head.next;
            ListNode next2 = head2.next;
            head.next = head2;
            head2.next = next1;
            head = next1;
            head2 = next2;
        }
    }

    // 876. 链表的中间节点,快慢指针法
    private ListNode middleNode(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

    // 206. 反转链表
    private ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        while (cur != null) {
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}
相关推荐
To_OC7 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
2401_841495648 小时前
【操作系统】进程同步与互斥实验报告
c++·算法·操作系统·进程·并发·同步·互斥
爱刷碗的苏泓舒12 小时前
PPP-AR 中的参考星选取:数学原理、评价指标与切换处理
算法·gnss·模糊度固定·ppp-ar·星间单差·参考星·卫星端偏差
烬羽15 小时前
递归老写崩?一个"退回"公式,把回溯题变成填空题
javascript·深度学习·算法
闪电悠米15 小时前
力扣hot100-41.缺失的第一个正数-原地哈希详解
数据结构·算法·哈希算法
星空露珠16 小时前
28种颜色对应名称,
开发语言·数据库·算法·游戏·lua
QXWZ_IA17 小时前
桥梁数字孪生怎么落地?
人工智能·科技·算法·智能硬件·政务
Kel17 小时前
输出层与反分词(Output Layer & Detokenization)
人工智能·算法·架构
陕西企来客18 小时前
2026年7月技术好GEO优化方案:算法适配与内容策略
人工智能·算法·机器学习·技术好geo优化