234. 回文链表

文章介绍了两种判断链表是否为回文的方法:一是通过复制链表到数组并使用双指针判断;二是利用递归从链表两端同时遍历并比较节点值。这两种方法分别针对不同的时间复杂度和空间复杂度需求。
摘要由CSDN通过智能技术生成

题目描述

给你一个单链表的头节点 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));
}

递归的具体过程

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值