题目描述
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例 1:
输入:head = [1,2,2,1]
输出:true
示例 2:
输入:head = [1,2]
输出:false
提示:
- 链表中节点数目在范围[1, 105] 内
- 0 <= Node.val <= 9
进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
解题思路
1.利用数组进行双指针判断
- 我们会用数组进行判断回文数,那么我们可以直接将链表之中的所有数据copy到数组之中在进行操作
bool isPalindrome(struct ListNode* head){
int a[100001];
int i=0;
struct ListNode* Head=head;
while(Head!=NULL)
{
a[i]=Head->val;
Head=Head->next;
i++;
}
int len=i;
for(i=0;i<(len/2);i++)//双指针操作
{
if(a[i]!=a[len-i-1])
return false;
}
return true;
}
2.递归判断
- 利用链表于递归的性质来进行操作也是一个好办法
- 为了方便我们理解递归,先看一个例子
#include<stdio.h>
#include<stdlib.h>
typedef struct NODE{
struct NODE* next;
int num;
}Node;
Node* head=NULL;
void insert(int x);
void Print(Node*head);
int main()
{
insert(1);
insert(2);
insert(3);
insert(4);
Print(head);
return 0;
}
void insert(int x)
{
Node* NEW=(Node*)malloc(sizeof(Node));
NEW->num=x;
NEW->next=NULL;
if(head==NULL)
head=NEW;
else
{
Node*temp=head;
while(temp->next!=NULL)
{
temp=temp->next;
}
temp->next=NEW;
}
}
void Print(Node *head)
{
if(head->next!=NULL)
Print(head->next);
printf("%d\n",head->num);
}
- 注意看最后一个打印函数,如果按照以往的思路,说不定你会以为它会正向打印
- 但是实际上它是逆向打印
- 这说明第二行的head->num所代表的head并不等同于从头开始遍历的head,而是反方向从尾部开始到头
struct ListNode*Head;//正向遍历的头节点
bool isPAL(struct ListNode* head)
{
if(head!=NULL)
{
if(!(isPAL(head->next)))//如果没有找到相对应的节点,返回false
{
return false;
}
if(head->val!=Head->val)//如果两者不同,返回false
return false;
Head=Head->next;//头节点向后遍历
}
return true;//如果均不是返回为真
}
bool isPalindrome(struct ListNode* head)
{
Head=head;
return (isPAL(head));
}