题干
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
想法
自然的想法是找到前半段后半段进行比对
那么就两个难点
怎么找到中间的点
以及怎么将后半段反转进行比对
因为是链表
中间节点自然想到快慢指针
然后将后半段反转即可比对
详见代码
Java代码
/**
* 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=head;
ListNode quick=head;
//现在slow的位置就是中间的那个节点
while(quick!=null&&quick.next!=null){
quick=quick.next.next;
slow=slow.next;
}
ListNode pre=null;
ListNode p=slow;
//中间节点以后的都反转
while(p!=null){
ListNode temp=p.next;
p.next=pre;
pre=p;
p=temp;
}
//两遍遍历 碰到不同的就false
while(pre!=null){
if(pre.val==head.val){
pre=pre.next;
head=head.next;
}
else{
return false;
}
}
return true;
}
}
以下是leetcode上更快的代码
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){ //边界条件头结点为空以及只有一个节点的情况
return true;
}
if(head.next.next==null){ //仅有连个节点的情况
return head.val == head.next.val;
}
ListNode slow = head;
ListNode fast = head.next;
while(fast.next!=null){ //针对于大于等于3个节点的链表,所以用slow与fast.next比较
if(slow.val == fast.next.val){
if(fast.next.next!=null){ //第一次是判断是不是第一个和最后一个相同(判断到达末节点)
return false;
}
else {
fast.next = null; //满足相同,则指后一个节点为空
slow = slow.next;//慢指针前移一步
fast = slow.next;//快指针比慢指针快一步
}
if(fast==null || (slow.val == fast.val&&fast.next==null)){ //判断是否过半(奇数个几点。此时s是单独的)或者中间两个相同,需判断fast.next是已判断过的,即为null(偶数个节点)
//(判断到达中间)
return true;
}
}else{
fast = fast.next; //若slow的值不等于fast.next,则fast 后移
}
}
return false;
}
}