题目描述:

【LeetCode234】Palindrome Linked List★-LMLPHP

解题思路:

  判断一个单向链表是否是回文链表,并且要求O(n)的时间复杂度和O(1)的空间复杂度。

  方法有以下几种:

  1、遍历整个链表,将链表每个节点的值记录在数组中,再判断数组是不是一个回文数组,时间复杂度为O(n),但空间复杂度也为O(n),不满足空间复杂度要求。

  2、利用栈先进后出的性质,将链表前半段压入栈中,再逐个弹出与链表后半段比较。时间复杂度O(n),但仍然需要n/2的栈空间,空间复杂度为O(n)。(起初选用了这种方法)

  3、反转链表法,将链表后半段原地翻转,再将前半段、后半段依次比较,判断是否相等,时间复杂度O(n),空间复杂度为O(1)满足题目要求。链表翻转可以参考LeetCode 206 Reverse Linked List的代码。

  第三种方法的核心在于,维护两个指针,慢指针一次移动一个,快指针一次移动两个,这样的结果是,快指针到达末尾时,慢指针到达中间。

  模拟如下图:

【LeetCode234】Palindrome Linked List★-LMLPHP

Java代码:

 //public class LeetCode234为测试代码
public class LeetCode234{
public static void main(String[] args) {
ListNode n1=new ListNode(1),n2=new ListNode(2),n3=new ListNode(4),n4=new ListNode(2),n5=new ListNode(1);
ListNode head=n1;
n1.next=n2;
n2.next=n3;
n3.next=n4;
n4.next=n5;
System.out.print("链表"+n1.val+"->"+n2.val+"->"+n3.val+"->"+n4.val+"->"+n5.val+"是否是回文链表:");
System.out.println(new Solution().isPalindrome(head));
}
}
class Solution {
public boolean isPalindrome(ListNode head) {
ListNode slow=head,fast=head;
while(fast!=null&&fast.next!=null){
slow=slow.next;//慢指针一次移动一个结点
fast=fast.next.next;//快指针一次移动两个结点
}
if(fast!=null)//结点个奇数为时会出现fast!=null,此时将slow右移一个
slow=slow.next;
slow=reverse(slow);
ListNode h=head;//定义h是为了不破坏原来链表
while(slow!=null){
if(h.val!=slow.val)
return false;
h=h.next;
slow=slow.next;
}
return true;
}
//reverse为反转链表,详见LeetCode206
public ListNode reverse(ListNode head){
ListNode pre=null;
ListNode current=head;
ListNode next=null;
while(current!=null){
next=current.next;
current.next=pre;
pre=current;
current=next;
}
return pre;
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}

程序结果:

【LeetCode234】Palindrome Linked List★-LMLPHP

04-24 19:01