题目:
编写一个函数,检查输入的链表是否是回文的。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
思路:
先将链表分成2个部分,将第2部分反转,然后逐一比较2个部分对应位置的值,如果都相等,则返回true;否则,返回false。注意完成后要将链表恢复成原来的状态,即将第2部分反转的链表再次反转,然后将第1部分和第2部分拼接。
关键点:
-
怎么将链表分成2半?
这里用快慢指针法,设置2个指针slow和fast开始都指向head节点,每次循环,slow走1步,fast走2步,这样fast走到链表末尾时,slow的位置就是链表的中间位置。
-
怎么反转?
设置3个指针pre,curr,nextNode,初始值分别为null,head,head.next,开始循环,每次循环时,curr.next指向他的前一个指针pre(curr.next= pre),然后更新指针,令pre = curr;curr = nextNode;nextNode = nextNode.next;结束条件为nextNode = null,结束循环后别忘了还有一个 指针curr.next没有反转,令curr.next = pre,此时curr为首节点,返回curr。
参考代码:
/**
先找到中间位置,然后将后一半位置反转,判断完成再反转,连接起来
*/
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null)return true;
//找到中间节点
ListNode fontHalfEnd = findHalfNode(head);
//后一半链表反转
ListNode h = resverse(fontHalfEnd.next);
ListNode p = head;
ListNode q = h;
while(p != null && q != null){
if(p.val != q.val)return false;
else{
p = p.next;
q = q.next;
}
}
//比完之后再对链表进行恢复
ListNode t = resverse(h);
fontHalfEnd.next = t;
return true;
}
查找中间结点函数如下:
public ListNode findHalfNode(ListNode head){
if(head == null || head.next == null)return head;
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
反转链表函数如下:
public ListNode resverse(ListNode head){
if(head == null || head.next == null)return head;
//设置3个指针
ListNode pre = null;
ListNode curr = head;
ListNode nextNode = head.next;
while(nextNode != null){
curr.next = pre;
pre = curr;
curr = nextNode;
nextNode = nextNode.next;
}
curr.next = pre;
return curr;
}