一、234. 回文链表
1.题目
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
2.分析
先回忆判断一个字符串是不是回文串:双指针法从两端向中间逼近
bool isPalindrome(string s) {
int left = 0, right = s.length - 1;
while (left < right) {
if (s[left] != s[right])
return false;
left++; right--;
}
return true;
}
但是单链表无法倒着遍历,无法使用双指针技巧,需要使用以下方法:
1、先通过 双指针技巧 中的快慢指针来找到链表的中点:
2、如果fast指针没有指向null,说明链表长度为奇数,slow还要再前进一步:
3、从slow开始反转后面的链表,现在就可以使用双指针法开始比较回文串了:
(还有一种思路是把原始链表反转存入一条新的链表,然后比较这两条链表是否相同。)
3.代码
package LinkedList;
/**
* @author: LYZ
* @date: 2022/4/10 15:26
* @description:
*/
public class IsPalindrome {
public static void main(String[] args) {
ListNode head = new ListNode(1, new ListNode(2, new ListNode(2, new ListNode(1))));
IsPalindrome isPalindrome = new IsPalindrome();
boolean ans = isPalindrome.isPalindrome(head);
System.out.println(ans);
}
public boolean isPalindrome(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
// 当fast!=0时跳出循环,即fast.next=null,此时链表节点个数为奇数
// 将slow再前进一位是为奇数链表的反转并用快慢指针做回文判断做准备
if (fast != null) {
slow = slow.next;
}
ListNode left = head;
ListNode right = reverse(slow);
while (right != null) {
if (left.val != right.val) {
// 注意比较的是左右指针指向的链表节点的val,不能比较指针(指针对应的是链表的节点及其后续所有节点)
return false;
}
left = left.next;
right = right.next;
}
return true;
}
ListNode reverse(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
// 初始化pre的值为null是因为链表最终应以null结尾,原地反转链表时需要让原链表的头节点指向null
// 当while循环结束时cur的值为null,所以很容易理解为什么return pre
return pre;
}
}