链表简单2 种解法
#234回文链表
判断单链表节点值从前向后与从后向前是否相同。
#链表#双指针#快慢指针
解题主线
01
复制到数组后可直接使用首尾双指针。
02
O(1) 额外空间方案用快慢指针找前半段末尾,反转后半段比较,最后恢复链表。
解法 1:数组 + 双指针
顺序收集节点值,再从数组两端向中间比较。
时间复杂度
O(n)
空间复杂度
O(n)
java
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)
java
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