请判断一个链表是否为回文链表。
示例1:
输入:1->2
输出:false
示例2:
输入:1->2->2->1
输出:true
进阶:
你能否用O(n)时间复杂度和O(1)时间复杂度解决此题?
我刚开始做的时候,首先想到的方法就是遍历到链表的最后一个节点,将最后一个节点与第一个节点比较,接着将最后一个节点置空,方便下一次比较的时候找到这次置空的节点的前一个节点,将比较后节点的下一个节点与置空的前一个节点再比较,将这些步骤重复,直到找到空节点为止。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
while(head != null){
//只有一个节点的时候,直接返回,它本身就是回文链表
if(head.next == null){
return true;
}
ListNode end = head;
ListNode tmp = null;
while(end.next != null){
tmp = end;
end = end.next;
}
if(end.val == head.val){
tmp.next = null;
head = head.next;
}else{
return false;
}
}
return true;
}
}
做完之后,发现这种做法的效率非常低,用时比较长。
然后我又想到了另一种做法,就是利用快慢指针,找到中间节点,然后将后半部分的节点逆置,一个节点指向头结点,另一个节点指向逆置后链表的头结点,两两比较。
这种方法的效率比第一种方法高的多。
/**
* 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 fast = head.next;
ListNode slow = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
ListNode secondhead = null;
//记录后半部分的头节点
ListNode second = slow.next;
slow.next = null;
while(second != null){
//临时变量,记录下一个节点
ListNode tmp = second.next;
second.next = secondhead;
secondhead = second;
second = tmp;
}
//链表的后半部分逆置,开始比较节点
while(secondhead != null && head.val == secondhead.val){
head = head.next;
secondhead = secondhead.next;
}
if(secondhead == null){
return true;
}else{
return false;
}
}
}