文章目录
前言
在面试中碰到这种题,需要考虑空间复杂度
一、回文结构是什么?
就是一个链表关于中点对称,或者关于中心轴对称
二、方法不断改进
1.直接放入栈判断
1.1思路
- 从头到尾遍历整个链表,将值放入栈中
- 在从头遍历链表,每到一个节点就出栈一个值
- 两个值相等就接着遍历
- 如果不相等就直接返回不是回文结构
- 如果直到栈为空了(或者头节点为空),就返回正确
1.2代码
public static boolean isPalindrome1(Node head) {
Stack<Node>stack = new Stack<Node>();
Node cur = head;
while(cur!=null) {
stack.push(cur);
cur=cur.next;
}
while(head!=null) {
if(head.value!=stack.pop().value) {
return false;
}else {
head=head.next;
}
}
return true;
}
2.放一半到栈
1.1思路
- 先让慢指针走一步,并且在快指针下个一个或者下两个为空的时候就停止
- 这样就可以在长度为奇数时,慢指针最终指向中点,偶数时,慢指针指向两个中点的后一位
- 接着将慢指针后面的全部入栈
- 在从头遍历链表,每到一个节点就出栈一个值
- 两个值相等就接着遍历
- 如果不相等就直接返回不是回文结构
- 如果直到栈为空了,就返回正确
1.2代码
public static boolean isPalindrome2(Node head) {
if(head==null||head.next==null) {
return true;
}
Node right = head.next;
Node cur = head;
Stack<Node> stack= new Stack<Node>();
while(cur.next!=null&&cur.next.next!=null) {
cur=cur.next.next;
right=right.next;
}
while(right!=null) {
stack.add(right);
right=right.next;
}
while(!stack.empty()) {
if(head.value!=stack.pop().value) {
return false;
}
head = head.next;
}
return true;
}
先改变后一半节点的指向,不用栈
1.1思路
- 快慢指针同时出发,当在快指针下个一个或者下两个为空的时候就停止
- 这样就可以在长度为奇数时,慢指针最终指向中点,偶数时,慢指针指向两个中点的前一位
- 接着弄一个指针(Java引用),慢指针不变,快指针到慢指针的后面一个,新建的指针到快指针后面,用三个指针改变链表指向的套路改变后面的指向
- 因为在改变完后,慢指针正好在最后一个节点,然后将快指针赋值到头节点
- 然后快慢指针的值比较
- 相等就继续遍历
- 如果不想等就返回不是回文结构
- 知道慢指针为空,就返回是回文结构
- 但是要注意最后要将链表复原,不能改变链表的结构
1.2代码
public static boolean isPalindrome3(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;
Node n3=null;
while(n2!=null) {
n3=n2.next;
n2.next=n1;
n1=n2;
n2=n3;
}
n3=n1;
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=n3.next;
n3.next=null;
while(n1!=null) {
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
总结
在笔试可以直接就用第一种方法,在面试就需要用最后的方法。为了淘汰其他人