题目:
给定一个链表的 头节点 head ,请判断其是否为回文链表。
如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。
解题思想:
1)利用栈的特性。先遍历链表存入栈中,然后比较头节点的值和压栈的值是否一致。(大多数人都能想到)
2)利用快慢指针。快慢指针:准备两个指针,慢指针每次走一下,快指针每次走两下;当快指针遍历完后,慢指针正好到链表的中间。然后后半段链表反转,和头节点比较。
代码1:(栈实现)
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
ListNode temp=head;
Stack<Integer> stack=new Stack<Integer>();
while(temp!=null){
System.out.println(temp.val);
stack.push(temp.val);
temp=temp.next;
}
while(stack.size()>0){
int pop=stack.pop();
if(pop!=head.val){
return false;
}
head=head.next;
}
return true;
}
(显然这个太Low了)
代码2:(快慢指针)
public boolean isPalindrome(ListNode head) {
//讨论0和1的情况
if (head.next == null || head == null) {
return true;
}
int count = 0;
ListNode temp1 = head;
while (temp1 != null) {//判断奇数偶数
count++;
temp1 = temp1.next;
}
ListNode temp2 = head;
temp1 = head;
if ((count + 1) % 2 == 0) {//奇数时候
while (temp2.next != null) {//快慢指针
temp1 = temp1.next;
temp2 = temp2.next.next;
}
temp1 = temp1.next;//链表反转
ListNode help = temp1.next;
temp2 = temp1;
temp2.next = null;
while (help!= null) {
temp1 = help;
help = temp1.next;
temp1.next = temp2;
temp2 = temp1;
}
while (temp1 != null) {//比较
if (head.val != temp1.val) {
return false;
}
head = head.next;
temp1 = temp1.next;
}
return true;
} else if ((count + 1) % 2 != 0) {//偶数时候
if (temp2.next.next == null) {//2的时候
if (temp1.val == temp2.next.val) {
return true;
}
return false;
} else {//大于2的偶数时候
//这里count其实判断奇数偶数的功能已经完成了
//但是奇数偶数的快慢指针有细微区别
//为了保证快指针到头时候慢指针在中点
//先让他们同时都走一步,然后快指针走两步,慢指针走一步
//不清楚的可以画画图
count = 1;
while (temp2.next != null) {//快慢指针
if (count == 1) {
temp1 = temp1.next;
temp2 = temp2.next;
count--;
}
temp1 = temp1.next;
temp2 = temp2.next.next;
}
//开始链表反转
ListNode help = temp1.next;
temp2 = temp1;
temp2.next = null;
while (help!= null) {
temp1 = help;
help = temp1.next;
temp1.next = temp2;
temp2 = temp1;
}
while (temp2 != null) {//比较
if (head.val != temp2.val) {
return false;
}
head = head.next;
temp2 = temp2.next;
}
return true;
}
}
return false;
}
解析: