题目描述
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。 给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
1->2->2->1
返回:true
解题思路:
不符合规范的两种思路(空间复杂度为O(N)):
1、如果是一个字符串/数组判定回文非常简单:用一个left下标从0开始,用一个right下标从最后一个位置开始;依次比较,如果left位置的元素和right位置的元素不相等,就不是回文,如果所有都相等,就是回文。
2、单向链表(只能从前往后,不能从后往前)
链表逆置:先把这个链表A复制一份得到链表B,再把这个链表B逆置一下,从A和B的开头依次往后遍历比较。
符合规范的思路(空间复杂度为O(1)):
3、先找到这个链表的中间结点(可能是奇数个节点,也可能是偶数个节点),从中间结点位置开始,对后半个链表进行逆置操作,从两个(半个)链表的开头依次遍历,进行比较即可。
代码实现:
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {
//1、先找到A链表的中间结点。
int size=size(A);
int steps=size/2;
ListNode B=A;
for(int i=0;i<steps;i++) {
B=B.next;
}
//2、从B开始对后面的链表进行逆置操作
ListNode prev=null;
ListNode cur=B;
while(cur!=null) {
ListNode next=cur.next;
if(next==null) {
//说明此时的cur已经是链表最后一个节点了,更新头节点的位置。
B=cur;
}
cur.next=prev;
prev=cur;
cur=next;
}
//3、分别从A和B出发,来依次对两个链表的元素判断是否对应相等
//如果链表长度为奇数,A和B的长度相同,无影响
//如果链表长度为偶数,A会比B长一个元素,此时要注意遍历链表的时候循环结束条件要以B为基准
while(B!=null) {
if(A.val!=B.val) {
//对应元素不同,说明不是回文结构
return false;
}
A=A.next;
B=B.next;
}
return true;
}
public int size(ListNode head) {
int size=0;
ListNode cur=head;
while(cur!=null) {
size++;
cur=cur.next;
}
return size;
}
}