链表简单2 种解法

#234回文链表

判断单链表节点值从前向后与从后向前是否相同。

#链表#双指针#快慢指针

解题主线

01

复制到数组后可直接使用首尾双指针。

02

O(1) 额外空间方案用快慢指针找前半段末尾,反转后半段比较,最后恢复链表。

解法 1数组 + 双指针

顺序收集节点值,再从数组两端向中间比较。

时间复杂度

O(n)

空间复杂度

O(n)

234. 回文链表 · 数组 + 双指针
final class ListNode {
    int val;
    ListNode next;

    ListNode(int val) {
        this.val = val;
    }
}

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

顺序收集节点值,再从数组两端向中间比较。

解法 2反转后半段并恢复

定位前半段末尾,反转后半段后逐节点比较,再反转回来恢复输入。

时间复杂度

O(n)

空间复杂度

O(1)

234. 回文链表 · 反转后半段并恢复
final class ListNode {
    int val;
    ListNode next;

    ListNode(int val) {
        this.val = val;
    }
}

final class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null) return true;
        ListNode firstHalfEnd = firstHalfEnd(head);
        ListNode reversed = reverse(firstHalfEnd.next);
        boolean palindrome = true;
        ListNode first = head;
        ListNode second = reversed;
        while (second != null) {
            if (first.val != second.val) {
                palindrome = false;
                break;
            }
            first = first.next;
            second = second.next;
        }
        firstHalfEnd.next = reverse(reversed);
        return palindrome;
    }

    private ListNode firstHalfEnd(ListNode head) {
        ListNode slow = head, fast = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

    private ListNode reverse(ListNode head) {
        ListNode previous = null;
        ListNode current = head;
        while (current != null) {
            ListNode next = current.next;
            current.next = previous;
            previous = current;
            current = next;
        }
        return previous;
    }
}

定位前半段末尾,反转后半段后逐节点比较,再反转回来恢复输入。

边界与易错点

  • 比较 Integer 时应比较数值而非对象引用。
  • 原地反转方案若不恢复链表,会给调用方留下隐蔽副作用。
整理来源

由旧仓库源码复核、去重并整理;展示代码已按 Java 21 语义修正明显问题。

easy/Q234_isPalindrome_linkedList.java