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;
    }
}
相关推荐
倒头就睡的小比特2 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼2 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光2 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark2 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her12 天前
并查集-听课笔记
笔记·算法·并查集
码流子2 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven2 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark2 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218612 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法