题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
算法思想:
- 先找到链表的中间节点(使用快慢指针的思想,其中有一道oj题目大家可以根据下面的思想自己写一下:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台),将整个链表分成两个子链表
- 将中间节点及其之后的链表进行反转
- 分别遍历两个链表进行回文判断
找到链表的中间节点
因为链表不像数组没有索引,所以不能直接通过索引以O(1)的时间复杂度得到某一个节点,可以使用快慢指针的思想,定义两个指针slow、fast,slow指针每次只走一步,fast指针每次走两步,循环的终止条件是fast=null或者fast.next=null(因为链表的长度可能为奇数可能为偶数),那么fast走完整个链表时slow指针刚好只走到链表的一半,此时slow指针所指向的节点刚好是中间节点:
public ListNode findMidNode(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
将中间节点及其之后的链表进行反转
链表的反转可以详细看我的另一篇博客:hot100:23反转链表-CSDN博客
ListNode cur = node.next;
node.next = null;
while(cur != null) {
ListNode nextCur = cur.next;
cur.next = node;
node = cur;
cur = nextCur;
}
进行回文的判断
此时整个链表已经被分成两个子链表了,分别是head到中间节点前一个节点以及中间节点之后反转后的链表,只需要分别遍历两个链表一一比对即可,循环的终止条件就是其中一个子链表为空即可
while(node != null) {
if(head.val != node.val) {
return false;
}
node = node.next;
head = head.next;
}
return true;
完整代码
public boolean isPalindrome(ListNode head) {
if(head == null) {
return true;
}
//1.先找到链表的中间节点
ListNode node = findMidNode(head);
//2.将后半部分的链表进行逆置
ListNode cur = node.next;
node.next = null;
while(cur != null) {
ListNode nextCur = cur.next;
cur.next = node;
node = cur;
cur = nextCur;
}
//3.进行回文链表的判断
while(node != null) {
if(head.val != node.val) {
return false;
}
node = node.next;
head = head.next;
}
return true;
}
public ListNode findMidNode(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}