Java关于重排链表详细解析

Java关于重排链表详细解析

问题描述

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

L0 -> L1 -> L2 -> ... -> Ln-1 -> Ln

需要将单链表 L 进行重新排列,使得新的链表既符合以下格式,也保留原链表元素的相对顺序:

L0 -> Ln -> L1 -> Ln-1 -> L2 -> Ln-2 -> ...

例如,将单链表 L = 1 -> 2 -> 3 -> 4 -> 5 -> 6 进行重排后,新链表应为 1 -> 6 -> 2 -> 5 -> 3 -> 4 。

解题思路

初步看到这道题目,我们很容易想到的是:将单链表拆成前半段与后半段,然后将后半段翻转,最后将前半段与后半段交叉拼接。

将单链表拆成前半段与后半段

首先,我们需要找到单链表 L 的中间节点,可以使用快慢指针的方法,一个指针每次向后移动 1 个节点,另一个指针每次向后移动 2 个节点,当快指针到达链表末尾时,慢指针恰好到达中间位置,这样便可以将单链表拆分成前半段与后半段。

int length = 0;
ListNode node = head;
while (node != null) {
    length++;
    node = node.next;
}

ListNode node1 = head;
ListNode node2 = null;

for (int i = 0; i < (length + 1) / 2; i++) {
    node2 = node1;
    node1 = node1.next;
}

node2.next = null; // 将链表断成两半

翻转后半段链表

接下来,我们需要对后半段链表进行翻转。这个问题不难,只需要使用三个指针,分别指向当前节点、前驱节点和后继节点,然后对当前节点的 next 指针进行反转即可。

/**
 * 翻转链表
 * @param head
 */
public void reverseList(ListNode head) {
    ListNode pre = null;
    ListNode cur = head;
    ListNode next = null;

    while (cur != null) {
        next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }
}

交叉拼接前半和后半段链表

最后,我们将前半段与翻转后的后半段依次交叉拼接即可。

ListNode cur1 = head;
ListNode cur2 = newHead;
ListNode next1 = null;
ListNode next2 = null;

while (cur2 != null) {
    next1 = cur1.next;
    next2 = cur2.next;

    cur1.next = cur2;
    cur2.next = next1;

    cur1 = next1;
    cur2 = next2;
}

完整代码:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public void reorderList(ListNode head) {
        if (head == null || head.next == null) {
            return;
        }

        // 将链表断成两半
        int length = 0;
        ListNode node = head;
        while (node != null) {
            length++;
            node = node.next;
        }

        ListNode node1 = head;
        ListNode node2 = null;

        for (int i = 0; i < (length + 1) / 2; i++) {
            node2 = node1;
            node1 = node1.next;
        }

        node2.next = null;

        // 翻转链表
        ListNode pre = null;
        ListNode cur = node1;
        ListNode next = null;

        while (cur != null) {
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }

        ListNode newHead = pre;

        // 交叉拼接前半和后半段链表
        ListNode cur1 = head;
        ListNode cur2 = newHead;
        ListNode next1 = null;
        ListNode next2 = null;

        while (cur2 != null) {
            next1 = cur1.next;
            next2 = cur2.next;

            cur1.next = cur2;
            cur2.next = next1;

            cur1 = next1;
            cur2 = next2;
        }
    }
}

示例说明

示例 1

单链表 L = 1 -> 2 -> 3 -> 4 -> 5 -> 6

中间节点为 3 ,将单链表拆分成前半段 1 -> 2 -> 3 和后半段 4 -> 5 -> 6

翻转后半段链表,得到 6 -> 5 -> 4

交叉拼接前半段和后半段链表,得到 1 -> 6 -> 2 -> 5 -> 3 -> 4

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java关于重排链表详细解析 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 使用Portainer部署Docker容器的项目实践

    使用Portainer部署Docker容器的项目实践攻略 1. 简介 Portainer是一个易于使用的Docker管理用户界面,可轻松管理Docker实例,容器,图像,卷和网络等资源。在本文中,我们将探讨如何使用Portainer将您的Docker容器部署到生产环境中。 2. 安装Portainer 为了使用Portainer,我们需要安装它。您可以通过以…

    other 2023年6月20日
    00
  • Hadoop源码分析六启动文件namenode原理详解

    Hadoop源码分析六启动文件namenode原理详解 一、概述 在Hadoop中,NameNode是整个分布式文件系统的组成部分,主要负责文件系统的管理和元数据的存储。本文将在分析Hadoop的启动文件时,结合源码讲解NameNode的启动过程及原理。 二、启动 NameNode 的步骤 启动 NameNode 的流程主要包括以下几个步骤: 1. 定义运行…

    other 2023年6月27日
    00
  • Word里的英文字母大小写怎么转换?

    在Word中,你可以使用以下方法来转换英文字母的大小写: 使用快捷键: 转换为大写字母:选中你想要转换的文本,然后按下\”Ctrl\”和\”Shift\”键,并同时按下\”A\”键。 转换为小写字母:选中你想要转换的文本,然后按下\”Ctrl\”和\”Shift\”键,并同时按下\”A\”键。 使用菜单选项: 转换为大写字母:选中你想要转换的文本,然后在Wo…

    other 2023年8月16日
    00
  • PHP 5.0创建图形的实用方法完整篇第1/3页

    PHP 5.0创建图形的实用方法完整篇 第1/3页 在PHP 5.0中,有多种方法可以创建和操作图形。以下是详细的攻略: 1. 使用GD库创建图像 GD库是一个常用的PHP图形库,可以用于创建和处理图像。以下是使用GD库创建图像的示例代码: // 创建一个空白图像 $image = imagecreatetruecolor(400, 300); // 设置背…

    other 2023年10月15日
    00
  • mac环境下python3安装及配置

    Mac环境下Python3安装及配置 Python是一种高级编程语言,广泛应用于Web开发、机器学习、数据分析等领域。在Mac环境下使用Python可以提高工作效率,但需要正确安装及配置Python,下面我们来介绍具体步骤。 步骤一:安装Homebrew Homebrew是Mac下最流行的包管理工具,用于简化软件安装过程。在Terminal中输入以下命令安装…

    其他 2023年3月28日
    00
  • win10右键intel显卡图形选项该怎么去掉?

    在 Win10 右键点击桌面空白处时,会出现一些选项,包括从 Nvidia 控制面板和 Intel 显卡设置中调整图形设置。如果你想要去掉 Intel 显卡图形选项,可以按照以下步骤进行。 步骤1:打开注册表编辑器 在 Windows 10 中按“Windows键+R”,输入regedit并按回车键打开注册表编辑器。 步骤2:导航到注册表位置 依次展开 HK…

    other 2023年6月27日
    00
  • Photoshop不能初始化暂存盘已满怎么办?

    问题描述:当使用 Photoshop 进行编辑时,可能会出现 Photoshop 不能初始化,暂存盘已满的错误提示。这种错误可能会导致 Photoshop 无法正常工作,从而影响到你的工作和生产。 攻略: 清理暂存盘空间 Photoshop 会将一些临时文件存储在暂存盘中,当暂存盘满了之后,就会出现此错误提示。因此,第一步需要清理暂存盘空间。 如果你不确定电…

    other 2023年6月20日
    00
  • pycharm打开命令行或Terminal的方法

    打开命令行或Terminal通常是程序员日常开发中必须要掌握的技能之一,下面我将介绍如何在PyCharm中打开命令行或Terminal。 PyCharm打开命令行 打开PyCharm,选择需要运行Python文件的项目。 在PyCharm窗口的底部工具栏中找到“Terminal”按钮,点击它。 会弹出一个命令行窗口,此时可以在其中输入需要执行的命令。 示例:…

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部