题目:
给定一个链表的头结点head,判断该链表是否为回文结构
例如:
1->2->1 返回 true;
1->2->3 返回 false; 要求时间复杂度为O(n),空间复杂度为O(1);
这道题目不能另设一个栈空间,只能通过链表标记指针将链表后半部分 逆序,在比较 相等为回文链表 不同返回false;
需要注意的是最后需要回复链表为之前的状态
代码:
#include <cstdio>
#include <iostream>
using namespace std;
struct node
{
int data;
struct node* next;
};
bool isPalindrome(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;
}//循环结束n1指向中点 n2指向尾结点
n2 = n1->next;//n2指向后半部分第一个结点
n1->next = NULL;//复用n1结点 将后半部分结点逆序
node *n3=NULL;
while (n2 != NULL)
{
n3 = n2->next;
n2->next = n1;
n1 = n2;
n2 = n3;
}//头插法循环结束后n1指向后半部分第一个结点 n2指向尾结点
n2 = head;
n3 = n1;//n3保存后半部分第一个节点的位置;
bool res = true;
while (n1 != NULL&& n2 != NULL)
{
if (n1->data != n2->data)
{
res = false;
break;
}
n1 = n1->next;
n2 = n2->next;
}
//例如head1当前顺序为1 2 3 1 2 同时n3指向后半部分的1 要恢复链表为 1 2 3 2 1
n1 = n3->next;
n3->next = NULL;
while (n1 != NULL)
{
n2 = n1->next;
n1->next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
int main()
{
node *head1 ,*head2;
head1 = new node;
head1->data = 1;
head1->next = new node;
head1->next->data = 2;
head1->next->next = new node;
head1->next->next->data = 3;
head1->next->next->next = new node;
head1->next->next->next->data = 2;
head1->next->next->next->next = new node;
head1->next->next->next->next->data = 1;
head1->next->next->next->next->next = NULL;
if (isPalindrome(head1)==true)
{
cout << "head1 = Yes" << endl;
}
else
{
cout << "head1 = No" << endl;
}
head2 = new node;
head2->next = new node;
head2->next->next = new node;
head2->next->next->next = new node;
head2->data = 1;
head2->next->data = 2;
head2->next->next->data = 3;
head2->next->next->next->data = 2;
head2->next->next->next->next = NULL;
if (isPalindrome(head2)==true)
{
cout << "head2 = Yes" << endl;
}
else
{
cout << "head2 = No" << endl;
}
return 0;
}