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) 高效且空间最优
相关推荐
可涵不会debug2 小时前
Redis魔法学院——第四课:哈希(Hash)深度解析:Field-Value 层级结构、原子性操作与内部编码优化
数据库·redis·算法·缓存·哈希算法
@––––––2 小时前
力扣hot100—系列1
算法·leetcode·职场和发展
老鼠只爱大米2 小时前
LeetCode经典算法面试题 #236:二叉树的最近公共祖先(RMQ转化、Tarjan离线算法等五种实现方案详细解析)
算法·leetcode·二叉树·lca·并查集·最近公共祖先·rmq
问好眼2 小时前
【信息学奥赛一本通】1296:开餐馆
c++·算法·动态规划·信息学奥赛
yxm26336690812 小时前
【洛谷压缩技术续集题解】
java·开发语言·算法
张人玉2 小时前
VisionPro Blob、条码识别、OCR 结构化速记版
人工智能·算法·机器学习·vsionpro
愚者游世3 小时前
力扣解决二进制&题型常用知识点梳理
c++·程序人生·算法·leetcode·职场和发展·改行学it
圣保罗的大教堂3 小时前
leetcode 3640. 三段式数组 II 困难
leetcode
Geoking.3 小时前
前缀和算法:从一道 LeetCode 题看区间求和优化思想
算法·leetcode·职场和发展