请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
思路:快慢指针+翻转链表
定义快指针fast和慢指针slow,fast每次走两步,慢指针每次走一步,循环截止,最后慢指针中间或者中间往前的位置。例如数组[1,2,3,4]
慢指针位于3,[1,2,3,4,5]
时慢指针也位于3。我们需要生成两个链表,对前者是2->1
和3->4
,对后者是2->1
和4->5
,然后依次判断是否相等,有不等返回false,否则true。
为了翻转链表,用pre表示翻转后的链表,默认为null,作为表尾节点,每次访问一个节点,将这个节点的next置为pre,当前节点做表头。用slow当做右半部分的链表。
最后,对于奇数个节点的链表来说,slow位于正中间,显然不行,需要左右对称,所以slow需要前进一位。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null)return true;
ListNode slow,fast,pre=null;
slow=fast=head;
while(fast!=null&&fast.next!=null){
ListNode cur=slow;
slow=slow.next;
fast=fast.next.next;
cur.next=pre;
pre=cur;
}
// System.out.println(slow.val);
if(fast!=null){
slow=slow.next;
}
while(pre!=null&&slow!=null){
// System.out.printf("%d-%d\n",pre.val,slow.val);
if(pre.val!=slow.val)return false;
pre=pre.next;
slow=slow.next;
}
return true;
}
}