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

阅读剩余 72%

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

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

相关文章

  • linux搭建squid代理服务器的完整步骤

    下面是详细讲解“Linux搭建Squid代理服务器的完整步骤”的攻略。其中,笔者以在Ubuntu 18.04系统上安装Squid为例介绍,其他系统可根据情况做相应调整。 1. 安装Squid 在终端输入以下命令,安装Squid: sudo apt-get update sudo apt-get install squid 2. 配置Squid 在安装完成后,…

    other 2023年6月27日
    00
  • 你好,FFMPEG 可视化

    你好,FFMPEG 可视化 在音视频处理中,FFMPEG 是一个非常常用的工具,它提供了丰富的命令行选项和参数,可以实现众多音视频处理任务。但是,对于不熟悉命令行的用户来说,FFMPEG 的使用可能会有一定的难度。为了让更多的用户能够方便地使用 FFMPEG,一些可视化的工具被开发出来。 FFMPEGX FFMPEGX 是一个 Mac 平台下的 FFMPEG…

    其他 2023年3月28日
    00
  • Java泛型之上界下界通配符详解

    Java泛型之上界下界通配符详解 在Java泛型中,通配符是一个非常强大的概念。它可以让我们在类型参数定义中使用限制,以控制传递给泛型的参数类型。本篇攻略将会详细讲解Java泛型中通配符的上界和下界以及如何使用通配符实现灵活而精细的类型限制。 上界通配符 我们知道在Java泛型中我们可以使用限定符来对类型参数进行限定,被限定的类型参数必须继承自该限定符指定的…

    other 2023年6月26日
    00
  • JS简单实现自定义右键菜单实例

    下面我会详细讲解如何简单实现自定义右键菜单的过程。 第一步:HTML结构准备 首先,需要定义一个HTML结构,包含菜单需要绑定的元素。 <!– 定义需要绑定右键菜单的区域 –> <div id="menu-wrap"> <ul id="context-menu" class=&quot…

    other 2023年6月27日
    00
  • Android实现TextView字符串关键字变色的方法

    当在Android中实现TextView字符串关键字变色时,可以使用SpannableString和ForegroundColorSpan来实现。下面是实现的完整攻略: 首先,在XML布局文件中定义一个TextView: <TextView android:id=\"@+id/textView\" android:layout_wi…

    other 2023年8月19日
    00
  • Linux中grep命令详解

    当然!下面是关于\”Linux中grep命令详解\”的完整攻略: … Linux中grep命令详解 在Linux中,grep命令用于在文件中搜索指定的模式。以下是两个示例: 示例1:在文件中搜索指定模式 $ grep \"pattern\" file.txt 在这个示例中,我们使用grep命令来搜索文件file.txt中的指定模式pa…

    other 2023年8月19日
    00
  • C语言长字符串的换行方法详解

    C语言长字符串的换行方法详解 介绍 在C语言程序设计中,我们经常需要声明一些较长的字符串,而当一个字符串太长时,不可避免地需要进行换行。本文将会讲解在C语言中如何进行长字符串的换行。 1. 转义字符 在C语言中,通过转义字符 \ ,可以将一行字符串拆分成多行,方便程序的阅读和维护。 例如,假设我们要声明一个较长的字符串: char *str = "…

    other 2023年6月20日
    00
  • java连接zookeeper实现zookeeper教程

    Java连接Zookeeper实现Zookeeper教程 在Java项目中,可以使用zookeeper来实现分布式锁、服务注册与发现等功能,本文将详细介绍Java如何连接zookeeper并实现相关功能。 1. Zookeeper简介 Zookeeper是用来实现分布式应用程序协调的开源软件,它是Google的Chubby的开源实现。Zookeeper的设计…

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