回文链表其实也是链表反转的变形;也可以用栈实现。
//对于一个链表,请设计一个时间复杂度为O(n), 额外空间复杂度为O(1)的算法,判断其是否为回文结构。
//给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
//测试样例:
//1->2->2->1
//返回:true
#include <stdio.h>
#include <iostream>
using namespace std;
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
//思路1:空间O(n) 整个链表遍历两边, 开一个栈,第一遍遍历把链表中每个元素push进栈中,这样堆中的元素的pop顺序就是链表的倒序输出;第二遍就开始pop栈中数据,每pop一个数据,就把这个数据跟链表中进行对比,如果相同继续往下走,如果不同返回false。
//
//思路2:空间O(1),使用快慢指针法,第一步设置一个块指针和一个慢指针,快指针一次走两步,慢指针一次走一步(慢),当快指针下一步为null的时候说明慢指针已经走了一半,这就可以找到中间节点。第二步反转中间链表后面的指针,第三部从头尾向中间扫描,对比每个元素是否相等,如果都相等,则是回文数,否则不是回文数。(下面网友易水给出了代码实现,这里不再叙述)
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
// write code here
ListNode* pSlow = A;
ListNode* pQucik = A;
//快慢指针找到中间节点
while (pQucik!=nullptr&&pQucik->next!=nullptr)
{
pQucik = pQucik->next->next;
pSlow = pSlow->next;
}
//将中点结点后的指针反转
ListNode* pNode = nullptr;
pNode = pSlow->next;
ListNode* pHead = pSlow; //反转链表的头
while (pNode!=nullptr) //测试未通过
{
ListNode* temp = pNode;
pNode = pNode->next;
temp->next = pHead;
pHead = temp;
}
while (A!=pHead)
{
if (A->val!=pHead->val)
{
return false;
}
A = A->next;
pHead = pHead->next;
}
return true;
}
};
class PalindromeList1 {
public:
bool chkPalindrome(ListNode* A) { //A不带头节点
// write code here
if (A == nullptr || A->next == nullptr)
return true;
ListNode* head = nullptr;
ListNode* node = A;
/* //将中间节点后的指针反转
ListNode* p = slow->next;
ListNode* p1 = p->next;
while (p != NULL){
p->next = slow;
slow = p;
p = p1;
p1 = p1->next;
}*/
while (node != nullptr){
ListNode* temp = node;
node = node->next;
temp->next = head;
head = temp;
}
while (A != nullptr&&head != nullptr){
if (A->val != head->val){
return false;
}
A = A->next;
head = head->next;
}
return true;
}
};
void print(ListNode* pHead)
{
if (pHead==nullptr)
{
puts("链表为空!");
return;
}
puts("链表为:");
ListNode*pNode = pHead->next;
while (pNode)
{
printf("%d ->", pNode->val);
pNode = pNode->next;
}
cout << "NULL\n";
}
ListNode* create()
{
ListNode* pHead, *pNode, *temp;
int x;
pHead = pNode = (ListNode*)malloc(sizeof(ListNode)); //带头节点的链表
printf("请输入链表数据,以0为结束标志:\n");
scanf("%d", &x);
while (x)
{
temp = (ListNode*)malloc(sizeof(ListNode));
temp->val = x;
pNode->next = temp;
pNode = temp;
scanf("%d", &x);
}
pNode->next = nullptr;
return pHead;
}
int main()
{
ListNode *pHead = create();
print(pHead);
PalindromeList s;
bool val=s.chkPalindrome(pHead);
cout << val << endl;
return 0;
}