回文链表
题目描述:
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
示例 1:
输入:head = [1,2,2,1] 输出:true
示例 2:
输入:head = [1,2] 输出:false
提示:
- 链表中节点数目在范围
[1, 105]
内 0 <= Node.val <= 9
进阶:你能否用 O(n)
时间复杂度和 O(1)
空间复杂度解决此题?
方法一思路分析:
反转链表的一半
使用快慢指针找到链表的中点:快指针每次移动两步,慢指针每次移动一步,当快指针到达链表末尾时,慢指针就位于链表的中点(对于奇数个节点的链表,慢指针位于中间两个节点的第一个)。
反转链表的后半部分:从慢指针开始,反转链表的后半部分。
比较前后两部分:将反转后的后半部分与原始链表的前半部分进行比较,如果每个节点都相等,则是回文链表。
代码实现:
public class Solution {
public boolean isPalindrome(ListNode head) {
// 如果链表为空或只有一个节点,直接返回true
if (head == null || head.next == null) {
return true;
}
// 使用快慢指针找到链表的中点
ListNode slow = head;
ListNode fast = head;
ListNode prev = null;
while (fast != null && fast.next != null) {
prev = slow;
slow = slow.next;
fast = fast.next.next;
}
// 如果链表长度为奇数,则跳过中点
if (fast != null) {
slow = slow.next;
}
// 反转链表的后半部分
ListNode secondHalfHead = reverseList(slow);
// 比较前半部分和反转后的后半部分
ListNode p1 = head;
ListNode p2 = secondHalfHead;
while (p2 != null) {
if (p1.val != p2.val) {
return false;
}
p1 = p1.next;
p2 = p2.next;
}
return true;
}
// 反转链表的方法
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
}
方法二思路分析:使用栈
遍历链表,将遍历到的每个节点的值压入栈中。然后,再次遍历链表,同时从栈中弹出元素,比较从链表中取出的元素和从栈中弹出的元素是否相等。如果所有元素都匹配,则链表是回文的。
public class Solution {
public boolean isPalindrome(ListNode head) {
Stack<Integer> stack = new Stack<>();
ListNode curr = head;
// 遍历链表,将值压入栈
while (curr != null) {
stack.push(curr.val);
curr = curr.next;
}
// 再次遍历链表,同时从栈中弹出元素进行比较
curr = head;
while (curr != null) {
if (curr.val != stack.pop()) {
return false;
}
curr = curr.next;
}
return true;
}
}
方法三思路分析:使用数组
遍历链表,将遍历到的每个节点的值存储在一个数组中。然后,使用双指针技术(一个从头开始,一个从尾开始)来比较数组中的元素。这种方法的空间复杂度是O(n),其中n是链表的长度。
public class Solution {
public boolean isPalindrome(ListNode head) {
List<Integer> vals = new ArrayList<>();
ListNode curr = head;
// 遍历链表,将值存储在数组中
while (curr != null) {
vals.add(curr.val);
curr = curr.next;
}
// 使用双指针比较数组中的元素
int i = 0, j = vals.size() - 1;
while (i < j) {
if (!vals.get(i).equals(vals.get(j))) {
return false;
}
i++;
j--;
}
return true;
}
}