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日

相关文章

  • C语言使用四种方法初始化结构体

    使用C语言可以使用以下四种方法来初始化结构体: 按成员顺序初始化 这是一种按照结构体的成员顺序来初始化结构体的方法。由于结构体成员顺序是固定的,所以可以将成员的值写在大括号中,并用逗号分隔。 示例代码如下: struct person { char name[20]; int age; char gender; }; // 使用按顺序初始化的方式初始化结构体…

    other 2023年6月20日
    00
  • mousewithoutborders无界鼠标使用教程

    mousewithoutborders无界鼠标使用教程 简介 Mouse Without Borders是由Microsoft Garage开发的一款跨平台无线鼠标共享工具。它允许多台电脑在同一个本地网络内分享同一个鼠标和键盘。 使用Mouse Without Borders,你可以将你的鼠标游走到多个屏幕之间,如在一台电脑上的左侧,通过在另一台电脑上的屏幕…

    其他 2023年3月28日
    00
  • 清理鼠标右键无用菜单 杜绝无用途内容

    清理鼠标右键无用菜单并杜绝无用途内容可以通过修改注册表实现,以下是详细攻略: 1. 打开注册表编辑器 在Windows系统中,按下Win+R组合键打开运行窗口,输入regedit命令后按下回车键,即可打开注册表编辑器。 2. 进入注册表项 依次展开HKEY_CLASSES_ROOT\Directory\Background\shell,这时可以看到很多对应于…

    other 2023年6月27日
    00
  • SpringIOC容器Bean的作用域及生命周期实例

    下面是Spring IOC容器Bean的作用域及生命周期实例的详细攻略: 1. 作用域 在Spring框架中,Bean的作用域指的是Bean的实例化范围。Spring框架提供了以下五种作用域: singleton:默认值,每个Bean都只有一个实例。 prototype:每次请求Bean时都会创建一个新实例。 request:在Web应用中,每个HTTP请求…

    other 2023年6月27日
    00
  • springboot 多环境配置 yml文件版的实现方法

    那我将为你详细讲解“springboot 多环境配置 yml文件版的实现方法”的攻略。 什么是Spring Boot多环境配置? Spring Boot 多环境配置是指,我们可以在不同的环境中使用不同的配置,比如开发环境、测试环境和生产环境等。这样,我们就可以在不同环境中使用不同的数据库连接,日志级别,开发端口等。 接下来,我们将学习如何在Spring Bo…

    other 2023年6月25日
    00
  • R语言-图形初阶

    R语言是一种用于数据分析和可视化的编程语言。在R语言中,图形是一种非常重要的数据可视化方式。本文将介绍R语言中图形初阶的完整攻略,包括绘制基本图形、添加注释和标签、设置图形属性等内容,并提供两个示例说明。 1. 绘制基本图形 在R语言中,我们可以使用plot()函数来绘制基本图形,例如散点图、折线图、柱状图等。下面是一个绘制散点图的示例: # 创建数据 x …

    other 2023年5月5日
    00
  • bat批处理的基本命令和使用方法

    BAT批处理的基本命令和使用方法 BAT批处理是Windows操作系统下的一种命令行脚本程序,用于自动化地执行一系列命令或操作。本文将详细讲解BAT批处理的基本命令和使用方法。 创建BAT批处理文件 在开始介绍BAT批处理的基本命令之前,我们需要先学习如何创建一个BAT文件。 打开记事本 输入批处理指令。如: @echo off echo Hello Wor…

    other 2023年6月26日
    00
  • 魔兽世界7.2.5敏锐贼怎么堆属性 wow7.25敏锐贼配装属性优先级攻略

    魔兽世界7.2.5敏锐贼怎么堆属性 WOW7.25敏锐贼配装属性优先级攻略 引言 敏锐贼是经典潜行贼的后续职业,在PVP中有着出色的表现。通过合适的属性堆叠和装备配装,可以让敏锐贼在战场中更加优秀。这篇攻略将会详细讲解敏锐贼如何堆叠属性以及装备的优先级。 属性堆叠 敏锐贼需要注重以下三个方面的属性堆叠:敏捷、暴击和精通。 敏捷 敏捷对敏锐贼来说最为重要,可以…

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