题目描述:对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
1->2->2->1
返回:true
求解思路:
空间复杂度O(N):逆置对比。将链表A复制一份给链表B,将链表B逆置,对比两链表是否相同。
空间复杂度O(1):找到链表A的中间节点,将链表后半部分逆置,对比前后两个半链表是否相同。
代码实现:
1.空间复杂度为O(N)
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {
if(A == null){
return true;
}
if(A.next == null){
return true;
}
//1.复制链表
ListNode newHead = new ListNode(0);
ListNode newTail = newHead;
for(ListNode cur = A;cur != null;cur = cur.next){
newTail.next = new ListNode(cur.val);
newTail = newTail.next;
}
ListNode B = newHead.next;
//2.逆置链表B
ListNode prev = null;
ListNode cur = B;
while(cur != null){
ListNode next = cur.next;
if(next == null){
B = cur;
}
//逆置
cur.next = prev;
//更新循环变量
prev = cur;
cur = next;
}
//3.对比两个链表是否相同
ListNode cur1 = A;
ListNode cur2 = B;
while(cur1 != null && cur2 != null){
if(cur1.val != cur2.val){
return false;
}
cur1 = cur1.next;
cur2 = cur2.next;
}
return true;
}
}
2、空间复杂度为O(1)
public class PalindromeList {
//计算链表长度
public int getLength(ListNode A){
int length = 0;
ListNode cur = A;
while(cur != null){
length++;
cur = cur.next;
}
return length;
}
public boolean chkPalindrome(ListNode A) {
//处理特殊情况
if(A == null){
return true;
}
if(A.next == null){
return true;
}
//1.寻找链表中间节点
int half = getLength(A) / 2;
ListNode cur = A;
for(int i = 0;i < half;i++){
cur = cur.next;
}
//
ListNode B = cur;
//2.逆置链表B
ListNode prev = null;
ListNode curNode = B;
while(curNode != null){
ListNode next = curNode.next;
if(next == null){
B = curNode;
}
//逆置
curNode.next = prev;
//更新循环变量
prev = curNode;
curNode= next;
}
//3.对比两个链表是否相同
ListNode cur1 = A;
ListNode cur2 = B;
while(cur1 != null && cur2 != null){
if(cur1.val != cur2.val){
return false;
}
cur1 = cur1.next;
cur2 = cur2.next;
}
return true;
}
}