Palindrome Linked List in Java2025 年 5 月 3 日 | 阅读 10 分钟 回文链表是指其元素序列从前向后读与从后向前读相同的链表。要确定一个链表是否是回文链表,我们需要在保持结构不变的情况下,比较链表的前半部分和反转后的后半部分。 回文链表示例输入:链表:1 -> 2 -> 3 -> 2 -> 1 输出:链表是否为回文? True 解释 链表 1 -> 2 -> 3 -> 2 -> 1 是回文链表,因为其序列从前向后读与从后向前读相同。通过反转后半部分(2 -> 1 变为 1 -> 2),它与前半部分(1 -> 2 -> 3)匹配,证实了该链表是回文链表。 方法 1:使用双指针技术算法步骤 1:检查链表是否为空或只有一个节点: 如果链表为空 (head == null) 或只有一个元素 (head.next == null),则它本身就是回文链表。函数立即返回 true。 步骤 2:找到链表中点: 使用两个指针:慢指针和快指针。慢指针一次移动一个节点,而快指针一次移动两个节点。当快指针到达链表末尾时,慢指针将位于链表中点。 步骤 3:反转链表的后半部分: 一旦慢指针到达中点,链表的后半部分(从慢指针开始)将被反转。这通过遍历后半部分并更改每个节点的 next 指针以指向其前一个节点来实现。完成此步骤后,链表的后半部分将被反转,并且慢指针将指向此反转后的后半部分链表的头部。 步骤 4:比较链表的两个部分: 现在,比较链表的前半部分(从头部开始)和反转后的后半部分(从慢指针开始)。 步骤 4.1:将两个指针移向各自部分末尾: 反转链表后半部分后,您现在有两个指针:一个从链表头部(前半部分)开始,另一个从反转后的后半部分头部(慢指针所在位置)开始。 步骤 5:使用两个指针: 一个从链表头部开始,另一个从反转后的后半部分开始。遍历两个部分,比较每个节点的数值。如果发现任何不匹配,则返回 false(表示链表不是回文)。如果所有数值都匹配,则返回 true(表示链表是回文)。 步骤 6:结论: 如果在比较过程中没有发现任何不匹配,则该链表是回文链表。 让我们使用 Java 程序实现上述算法。 文件名:PalindromeLinkedList.java 输出 Is the linked list a palindrome? true 复杂度分析时间复杂度此算法的时间复杂度为 O(n),因为我们遍历链表两次:一次找到中点,一次比较两个部分。反转后半部分也需要 O(n)。由于没有使用额外的空间,因此复杂度为 O(1)。 空间复杂度 此算法的空间复杂度为 O(1),因为它只使用了常数级别的额外空间。它依赖于几个指针变量来遍历和操作链表,但没有使用任何额外 数据结构 或数组,使其空间效率高。 方法 2:使用栈算法步骤 1:处理边缘情况: 如果链表为空 (head 为 null) 或只有一个节点 (head.next 为 null),我们可以立即得出结论,它是一个回文链表。单个元素或空列表正反读都相同,因此返回 true。 步骤 2:初始化两个指针: 我们使用两个指针,慢指针和快指针。两者都从链表头部开始。慢指针一次移动一个节点,而快指针一次移动两个节点。速度上的差异使我们能够找到链表中点。当快指针到达链表末尾时,慢指针将位于中点。这是因为快指针的移动速度是慢指针的两倍。 步骤 3:将链表前半部分压入堆栈: 随着慢指针沿着链表移动,我们将当前节点的值压入堆栈。堆栈遵循“后进先出”(LIFO) 原则,这意味着链表前半部分的值将按反向顺序存储。跳过中间元素(如果链表长度为奇数) 步骤 3.1: 如果链表包含奇数个元素,当慢指针到达中点时,快指针将不为 null。在这种情况下,我们将慢指针向前移动一步以跳过中间元素。此步骤确保我们只比较链表的后半部分与存储在堆栈中的前半部分。 步骤 4:将链表后半部分与堆栈进行比较: 现在,慢指针位于链表后半部分的开头。我们开始将此后半部分的每个节点与从堆栈中弹出的值进行比较。对于后半部分的每个节点,我们从堆栈中弹出一个值,并检查它是否与当前节点的值匹配。如果任何时候值不匹配,我们将返回 false,因为链表不是回文。 步骤 5:返回结果: 如果我们到达后半部分的末尾,并且后半部分的所有值都与从堆栈中弹出的值匹配,我们就得出结论,该链表是回文链表,并返回 true。 让我们使用 Java 程序实现上述算法。 文件名:PalindromeLinkedList.java 输出 Is the linked list a palindrome? true 复杂度分析时间复杂度此算法的时间复杂度为 O(n),其中 n 是链表中的节点数。我们遍历链表两次:一次将前半部分压入堆栈,一次将后半部分与 堆栈 进行比较,这两者都需要线性时间。 空间复杂度此算法的空间复杂度为 O(n),其中 n 是链表中的节点数。这是因为使用了堆栈来存储链表前半部分的元素以进行比较。除了堆栈外,不需要额外的数据结构。 方法 3:使用递归算法步骤 1:设置递归: 使用递归的思想是从头部遍历链表直到尾部,并在递归展开时比较开始和结束的节点。递归函数将遍历链表并回溯以检查对称性,而无需显式反转链表。 步骤 2:初始化:frontPointer: 初始化一个指针 (frontPointer) 指向链表头部。在递归回溯期间,它将跟踪来自前方的当前节点。我们通过调用 recursivelyCheck(head) 来初始化递归,其中 head 是链表的起始节点。 步骤 3:基本情况(递归结束条件): 在任何递归函数中,都需要一个基本情况来停止进一步的递归调用。对于回文检查,基本情况是到达链表末尾。条件:当当前节点为 null 时,表示我们已到达链表末尾。此时,我们返回 true,因为我们尚未遇到任何不匹配。 步骤 4:递归步骤(遍历到末尾): 随着我们递归地调用 recursivelyCheck(current.next),函数会逐个节点向前移动链表,直到到达末尾。递归继续而不检查回文属性;它只关心到达基本情况。 步骤 5:回溯和比较: 在递归开始展开后(即到达基本情况),我们开始比较节点。关键思想是将当前节点的值与由 frontPointer 跟踪的列表前面的值进行比较。 步骤 6:比较: 在每次回溯级别,我们将当前节点的值与 frontPointer 指向的节点的值进行比较。如果值不匹配,我们将立即返回 false,因为链表不是回文。 步骤 7:最终检查: 如果递归函数完成了所有比较并且节点继续匹配,则函数将返回 true,表示链表是回文链表。如果在任何时候发现不匹配,递归将立即返回 false,并且链表将被视为非回文链表。 步骤 8:函数返回值: 链表是否为回文的最终结果将返回给开始检查的主函数。结果取决于从前面和后面的所有节点对是否匹配。 让我们使用 Java 程序实现上述算法。 文件名:PalindromeLinkedList.java 输出 Is the linked list a palindrome? true 复杂度分析时间复杂度递归回文检查的时间复杂度为 O(n),其中 n 是链表中的节点数。递归期间每个节点都会被访问一次,并且在递归展开的每一步都会进行当前节点与 frontPointer 之间的比较。 空间复杂度递归回文检查的空间复杂度为 O(n),这是因为使用了用于递归的调用堆栈。每个递归调用都会向堆栈添加一个新帧,在最坏的情况下,递归深度与链表中的节点数成正比。 下一个主题Java 中的截断是什么 |
Java Queue 接口是 Java 集合框架的重要组成部分,它提供了队列数据结构的实现。它遵循先进先出 (FIFO) 原则,其中元素在末尾插入,在开头移除。本文将探讨...
阅读 4 分钟
在本节中,我们将学习如何使用星号或其他特殊字符编写 Lord 的代码。这是 Java 中最难编写的模式程序之一。我们将使用“for”循环来打印 Lord… …
阅读 2 分钟
在面向对象编程中,抽象被定义为隐藏用户不需要的细节(实现),而专注于基本信息(功能)。它提高了效率并降低了复杂性。在 Java 中,可以通过抽象类和抽象方法来实现抽象。抽象方法 在 Java 中,抽象方法是...
5 分钟阅读
在 Java 中,final 类是不能被任何其他类扩展(继承)的类。换句话说,没有人可以创建 final 类的子类。我们可以使用 final 关键字将一个类声明为 final。final class Fruits { ...
阅读 6 分钟
引言 503 错误是在访问网站或 Web 应用程序时最常见和最令人沮丧的错误之一。当查看网页或使用某些基于 Web 的应用程序时,通常会看到此错误。错误代码表示服务器暂时无法处理请求...
阅读 6 分钟
在 Java 中,Stream API 负责存储在 Java 8 版本中引入的 mapToInt() 方法。mapToInt() 方法的主要目的是将流中的元素转换为 IntStream。让我们详细了解 mapToInt() 方法……
阅读9分钟
? Java 是一种强大的编程语言,它提供了许多有效的方法来处理和使用数组。将数组传递给函数是数组操作的关键部分。程序员可以通过将数组作为函数参数来执行操作,直接操作数组项。在此...
阅读 8 分钟
Java 中的 getClass() 方法是继承自 Object 类的一个基本方法,Object 类是 Java 类层次结构的根。它允许我们检索对象的运行时类。Java 中的每个类都直接或间接继承自该类。...
阅读 13 分钟
排序是将列表或数组的元素按特定顺序排列的一种方法。顺序可以是升序或降序。数值顺序和字典序(字母顺序)是一种广泛使用的顺序。在本节中,我们将学习如何对数组进行排序...
阅读 6 分钟
火星探测器问题是一个经典的编程挑战,它考验一个人设计算法在矩形网格上导航探测器的能力。目标是根据一组命令来操纵探测器,避开障碍物并保持在边界内...
阅读 6 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India