请判断一个链表是否为回文链表。
示例 1:
输入: 1->2 输出: false
示例 2:
输入: 1->2->2->1 输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
我的思路:先计算链表的长度,然后申请一个与其等长的数组,将链表中值复制到数组中,在数组中判断是否为回文!
代码:简单,但低效!
bool isPalindrome(struct ListNode* head) {
if(!head) return true;//链表为空时
struct ListNode* p=head;
struct ListNode* q=head;
int i=1;
//链表长度为1时
if(p->next==NULL) return true;
//长度大于1时:先计算链表长度,再定义数组,把链表的值全部导如数组,循环遍历数组至数组长度二分之一处以验证是否为回文数组
while(q->next!=NULL)
{
i++;
q=q->next;
}
int a[i+1];
int j=0;
while(p->next!=NULL)
{
a[j]=p->val;
j++;
p=p->next;
}
a[j]=p->val;
for(i=0;i<(j+1)/2;i++)
{
if(a[i]!=a[j-i]) return false;
}
return true;
}
进阶思路:找到链表的中间位置,然后将中间位置的左半部分的链表逆序反转,右半部分不变。之后就可以愉快地判断是否为回文链表了!
下面的代码,效率高,逻辑性强,值得学习!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//连表翻转函数
struct ListNode* reverse_list(struct ListNode* head){
if(!head){
return NULL;
}
struct ListNode* prev = NULL;
struct ListNode* now = head;
struct ListNode* next = NULL;
while(now){
next = now->next;
now->next = prev;
prev = now;
now = next;
}
return prev;
}
bool isPalindrome(struct ListNode* head) {
if(!head){
return true;
}
struct ListNode* ptr1 = head;
struct ListNode* ptr2 = head;
struct ListNode* mid = NULL;
while(1){
ptr2 = ptr2->next;
if(ptr2){
ptr2 = ptr2->next;
if(!ptr2 || !ptr2->next){
mid = ptr1; //偶数个偏左
break;
}
}else{
mid = ptr1; //奇数个正中间
break;
}
ptr1 = ptr1->next;
}
ptr2 = mid->next;
mid->next = NULL;
ptr2 = reverse_list(ptr2);
ptr1 = head;
while (ptr1 && ptr2){
if(ptr1->val != ptr2->val){
return false;
}
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}
return true;
}