每日一题—— 判断一个链表是否为回文结构(快慢指针,对撞指针)

文章介绍了如何判断一个链表是否为回文结构,提供了两种方法:一是使用快慢指针将链表一分为二,然后比较两部分是否相同;二是将链表元素存入数组,用对撞指针比较头尾元素。两种方法均在找到不匹配元素时返回false,否则返回true。
摘要由CSDN通过智能技术生成

每日一题

判断一个链表是否为回文结构

题目链接

在这里插入图片描述

思路

由题可知:回文结构即字符串正序逆序完全一致,如“1 2 3 4 3 2 1”,那么我们就要想办法同时比较链表头和链表尾的元素,看其是否相等。

方法一(快慢指针)
  • 首先遍历链表,求出其长度length。

  • 由于单链表不能逆序遍历,所以我们可以利用快慢指针将链表一分为二

    • 定义指针变量left,mid,right,使其分别指向头结点·,头的下一个节点,头的下下个节点。每次同时让left,mid走一个节点,right走两个节点,当right为空,或right的下一个节点为空时,说明right已经走到表尾,此时mid即为链表的中间,令left的指针域为空,即可将链表一分为二。
  • 如果链表长度length为偶数,那么翻转以mid为头节点的链表,便于与另一个链表比较。

    • 如图:在这里插入图片描述
  • 如果链表长度length为奇数,那么就翻转以mid->next为头结点的链表。

    • 如图:在这里插入图片描述
  • 最后,再将两个链表的元素逐个进行比较,只要出现不相等的情况,直接返回false,若两链表遍历完都没有出现不相等的情况,则返回true

方法一实现代码
/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

/**
 * 
 * @param head ListNode类 the head
 * @return bool布尔型
 */
bool Compare(struct ListNode *head1,struct ListNode *head2)		//比较两链表元素
{
    while(head1 && head2)
    {
        if(head1->val != head2->val)
            return false;
        head1 = head1->next;
        head2 = head2->next;
    }
    return true;
}
struct ListNode* Filp(struct ListNode *head)	//反转链表
{
    struct ListNode *newHead = (struct ListNode *)malloc(sizeof(struct ListNode));
    newHead->next = head;
    struct ListNode *pre = newHead, *cur = head;
    while(cur->next)
    {
        struct ListNode *temp = cur->next;
        cur->next = temp->next;
        temp->next = pre->next;
        pre->next = temp;
    }
    return newHead->next;
}
bool isPail(struct ListNode* head ) {
    if(head == NULL || head->next == NULL)		//如果链表只有一个或没有元素,则直接为回文结构,返回true
        return true;
    struct ListNode* cur = head;
    struct ListNode *left = head, *mid = head->next, *right = head->next->next;
    int count=0;
    while(cur)
    {
        count++;		//求出链表长度
        cur = cur->next;
    }
    while(right && right->next)
    {
        left = left->next;
        mid = mid->next;
        right = right->next->next;
    }
    left->next = NULL;		//分割链表
    if(count % 2)		//判断长度的奇偶
        return Compare(head,Filp(mid->next));
    else
        return Compare(head, Filp(mid));
}
方法二(对撞指针)
  • 单链表不能逆序遍历,但数组可以呀。因此我们可以遍历链表元素,并将其存入数组中。
  • 利用对撞指针的思想,;不断比较数组的头尾元素,只要出现不相等的情况,直接返回false,若遍历完数组都没有出现不相等的情况,则返回true
方法二实现代码
/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

/**
 * 
 * @param head ListNode类 the head
 * @return bool布尔型
 */
bool isPail(struct ListNode* head ) {
    struct ListNode* cur = head;
    int count=0;
    int *num;
    while(cur)
    {
        count++;		//求出链表长度
        cur = cur->next;
    }
    num = (int *)malloc(sizeof(int) * count);		//申请数组内存
    for(int i = 0;i < count;i++)		//将链表数据存入数组
    {
        num[i] = head->val;
        head = head->next;
    }
    for(int i = 0,j = count-1;;i++,j--)		//分别从头尾比较数组元素
    {
        if(j <= i)	//如果j小于等于i,说明两指针已经相遇,即已经比较完毕,未出现不等情况,直接返回true
            return true;
        if(num[i] != num[j])	//只要出现不等的情况,直接返回false
            return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Forward♞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值