链表结构
public static class Node{
int value;
Node next;
public Node(int value) {
this.value=value;
}
}
方法一:使用一个栈,通过遍历链表存入栈中,栈在弹出的过程中就是链表的逆序,辅助空间o(n)
public static boolean isPalindromeList1(Node head) {
Stack<Integer> stack=new Stack<>();
Node head1=head;
while(head1!=null)
{
stack.push(head1.value);
head1=head1.next;
}
while(head!=null)
{
if(head.value!=stack.pop())
return false;
head=head.next;
}
return true;
}
方法二:利用一个快指针和一个慢指针,当快指针走到链表末尾时,慢指针走到链表中间,把慢指针及以后的入栈,再来跟链表头结点一一对比下去。辅助空间为O(n/2)
public static boolean isPalindromeList2(Node head) {
Stack<Integer> stack=new Stack<>();
if(head==null||head.next==null)
return true;
Node slow=head;
Node fast=head;
while(fast.next!=null&&fast.next.next!=null)
{
slow=slow.next;
fast=fast.next.next;
}
while(slow!=null)
{
stack.push(slow.value);
slow=slow.next;
}
while(!stack.isEmpty())
{
if(head.value!=stack.pop())
return false;
head=head.next;
}
return true;
}
方法三:利用一个快指针和一个慢指针,当快指针走到链表末尾时,慢指针走到链表中间,把慢指针以后的节点都转向直接或者间接指向中间节点的方向,令中间节点(慢指针所指)指向null之后再通过链表头和链表尾开始遍历比较,辅助空间为O(1)。在改变了中间节点以后的链表结构后,再判断回文后,链表应改变回来。
public static boolean isPalindromeList3(Node head) {
if(head==null||head.next==null)
return true;
Node n1=head;
Node n2=head;
while(n2.next!=null&&n2.next.next!=null)
{
n1=n1.next;
n2=n2.next.next;
}
n2=n1.next;//等于中间节点的下一个
n1.next=null;//中间节点下一个指向null
Node temp=null;
while(n2!=null)//逆转中间节点以后的链表节点
{
temp=n2.next;
n2.next=n1;
n1=n2;
n2=temp;
}
temp=n1;//temp这时是链表的最后一个节点
n2=head;
boolean res=true;
while(n1!=null&&n2!=null)
{
if(n1.value!=n2.value)
{
res=false;
break;
}
n1=n1.next;
n2=n2.next;
}
//中间节点以后的链表指向改变回来
n1=temp.next;
temp.next=null;
while(n1!=null)
{
n2=n1.next;
n1.next=temp;
temp=n1;
n1=n2;
}
return res;
}
调整链表方向过程大概如下
(1)
(2)
(3)
就是如此循环下去。。。。。。