一、什么是回文链表?
回文两个字大家一定不陌生,在学习C语言时一定接触过回文。
比如:
一个字符串的逆序
我们定义一个数组里面有这些元素{1,2,3,4,5,4,3,2,1}那么如何判断它是不是回文的呢?
我们通常一般是从头和尾开始进行操作判断,如此便可以知到这个数字是不是回文。
int left = 0, right = strlen(str);
while(left < right)
{
if(str[left] != str[right])
break;
left++;
right--;
}
这样便可以判断了这个数组是不是回文了。那么链表是不是也可以呢?当然可以。
第一步:遍历整个链表,将链表值复制到数组当中。
第二部:使用双指针法判读是不是为回文。
但这样所使用的时间复杂度为O(n),空间复杂度也为O(n)。这会使我们的空间复杂度不尽人意。那么有没有什么办法可以让它优化一下空间复杂度呢?
二.进阶空间复杂度O(1)
要想空间复杂度为o(1),我们不能再开辟空间了,那么有没有什么办法可以找到链表的中间位置然后在想办法呢?
n/2+n/2=n;
上面的数学公式想必小学就学过吧,如果a走出了两步和b一步相同,那么a和b同时走a会始终落后b一半。因此我们也可以让一个指针走快点一个走慢点也可以达到此效果。
我们可以定义一个快指针
ListNode* quite=head;
一个慢指针
ListNode* slow=head;
每当快指针走两步时慢指针走一步
while(quite!=NULL&&quite->next!=NULL)
{
quite=quite->next->next;
slow=slow->next;
}
裁判测试样例就不给了,接下来请看函数:
bool isPalindrome(ListNode* head)
{
ListNode* quite=head;//快指针
ListNode* slow=head;//慢指针
while(quite!=NULL&&quite->next!=NULL)
{
quite=quite->next->next;//快指针走两步慢指针走一步
slow=slow->next;
}
ListNode* node=reverseList(slow);
ListNode* L=head;
while(L!=NULL&&node!=NULL)
{
if(node->val!=L->val)
return false;
node=node->next;
L=L->next;
}
return true;
}
ListNode* reverseList(ListNode* head)
{
ListNode* List=head;
ListNode* sed=head;
ListNode* L=NULL;
while(List!=NULL)
{
sed=List->next;
List->next=L;
L=List;
List=sed;
}
return L;
}