LeetCode Hot100(21/100)——234. 回文链表

文章目录

一、题目理解

题目链接: Palindrome Linked List

题目描述:

给定一个单链表的头节点 head,判断该链表是否为回文链表。

如果链表从前往后与从后往前的节点值序列相同,则认为是回文。

示例:

复制代码
输入:head = [1,2,2,1]
输出:true

输入:head = [1,2]
输出:false

二、问题分析

我们要判断链表的节点值序列是否是回文结构。

具体而言,若链表的值为 1 -> 2 -> 3 -> 2 -> 1,从前往后与反向的值序列一致,此时返回 true

链表无法直接随机访问,因此不能像数组那样轻易反转或双指针比较,需要借助额外手段。


三、解法一:数组辅助法(最易理解)

核心思路

将链表中的节点值依次存入数组,然后利用数组的下标进行首尾双指针对比。

步骤解析(流程图)





开始
创建空数组 list
遍历链表,将节点值存入 list
设置左右指针 left=0, right=list.size()-1
list[left] == list[right]?
返回 false
left++, right--
left >= right?
返回 true

时间与空间复杂度

  • 时间复杂度: O(n)
    遍历链表一次存入数组,再遍历一半数组比较。
  • 空间复杂度: O(n)
    需要一个额外的数组存储节点值。

Java代码实现

java 复制代码
class ListNode {
    int val;
    ListNode next;
    ListNode(int val) { this.val = val; }
}

public class Solution {
    public boolean isPalindrome(ListNode head) {
        List<Integer> list = new ArrayList<>();
        ListNode node = head;
        while (node != null) {
            list.add(node.val);
            node = node.next;
        }
        int left = 0, right = list.size() - 1;
        while (left < right) {
            if (!list.get(left).equals(list.get(right))) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

四、解法二:快慢指针 + 反转链表(空间优化)

核心思路

  1. 使用快慢指针 找到链表的中点。
    • 快指针每次走两步,慢指针每次走一步,当快指针到达末尾时,慢指针就在中间位置。
  2. 将后半部分链表反转
  3. 从链表头开始与反转后的后半部分进行逐节点比较
  4. 若全部相同则为回文。

关键步骤图示

找中点
slow
fast
1
2
3
2
1

反转后半部分:
1
2
3
2
1

对比:
反转后半部分 前半部分 反转后半部分 前半部分 若有不同则非回文 比较节点值是否相等 向下一个节点移动

时间与空间复杂度

  • 时间复杂度: O(n)
    找中点 O(n/2),反转 O(n/2),比较 O(n/2)。
  • 空间复杂度: O(1)
    只使用常量指针变量。

Java代码实现

java 复制代码
public class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) return true;
        
        // 1. 快慢指针找到中点
        ListNode slow = head, fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }

        // 2. 反转后半部分链表
        ListNode secondHalf = reverseList(slow);

        // 3. 从头与反转后的后半比较
        ListNode firstHalf = head;
        while (secondHalf != null) {
            if (firstHalf.val != secondHalf.val) {
                return false;
            }
            firstHalf = firstHalf.next;
            secondHalf = secondHalf.next;
        }
        return true;
    }

    private ListNode reverseList(ListNode head) {
        ListNode prev = null, curr = head;
        while (curr != null) {
            ListNode nextNode = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextNode;
        }
        return prev;
    }
}

五、总结

解法 核心思路 时间复杂度 空间复杂度 特点
数组辅助法 用数组保存节点值再比较 O(n) O(n) 简单易理解
快慢指针+反转法 找中点后反转后半部分比较 O(n) O(1) 高效且空间最优
相关推荐
sinat_255487814 小时前
为 System.out 编写我们自己的包装类
java·开发语言·算法
阿Y加油吧4 小时前
力扣打卡——盛最多水的容器、三数之和
算法·leetcode·排序算法
Barkamin4 小时前
快速排序非递归实现
java·算法·排序算法
gihigo19984 小时前
距离角度解耦法的MIMO-OFDM雷达波束形成及优化MATLAB实现
开发语言·算法·matlab
WolfGang0073214 小时前
代码随想录算法训练营 Day12 | 二叉树 part02
算法·深度优先
2401_853576504 小时前
代码自动生成框架
开发语言·c++·算法
逆境不可逃4 小时前
【从零入门23种设计模式23】行为型之模板模式
java·开发语言·算法·设计模式·职场和发展·模板模式
ZPC82105 小时前
PPO 在ROS2 中训练与推理
人工智能·算法·机器人
IronMurphy5 小时前
【算法二十五】105. 从前序与中序遍历序列构造二叉树 236. 二叉树的最近公共祖先
java·数据结构·算法
2401_853576505 小时前
C++中的组合模式变体
开发语言·c++·算法