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

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

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

题目链接

思路

由题可知:回文结构即字符串正序逆序完全一致,如“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;
    }
}


相关文章
|
24天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
29 1
|
1月前
链表指针的传参,传值和传地址
本文讨论了链表操作中指针传参的问题,特别是指针的传值与传地址的区别,并提供了修正代码,以确保链表插入操作能正确地修改指针指向的地址。
17 1
链表指针的传参,传值和传地址
|
1月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
18 0
|
1月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
24 0
|
3月前
【刷题记录】链表的回文结构
【刷题记录】链表的回文结构
|
4月前
【数据结构OJ题】复制带随机指针的链表
力扣题目——复制带随机指针的链表
51 1
【数据结构OJ题】复制带随机指针的链表
|
3月前
|
Python
【Leetcode刷题Python】138. 复制带随机指针的链表
LeetCode上题目“138. 复制带随机指针的链表”的Python解决方案,包括两种方法:一种是在每个节点后复制一个新节点然后再分离出来形成新链表;另一种是构建一个字典来跟踪原始节点与其副本之间的映射关系,从而处理新链表的构建。
21 1
|
3月前
|
存储 Java 开发者
揭秘!HashMap底层结构大起底:从数组到链表,再到红黑树,Java性能优化的秘密武器!
【8月更文挑战第24天】HashMap是Java集合框架中的核心组件,以其高效的键值对存储和快速访问能力广受开发者欢迎。在JDK 1.8及以后版本中,HashMap采用了数组+链表+红黑树的混合结构,实现了高性能的同时解决了哈希冲突问题。数组作为基石确保了快速定位;链表则用于处理哈希冲突;而当链表长度达到一定阈值时,通过转换为红黑树进一步提升性能。此外,HashMap还具备动态扩容机制,当负载因子超过预设值时自动扩大容量并重新哈希,确保整体性能。通过对HashMap底层结构的深入了解,我们可以更好地利用其优势解决实际开发中的问题。
104 0
|
3月前
|
存储 算法 数据处理
指针与链表
指针与链表
65 0
|
4月前
【数据结构OJ题】链表的回文结构
牛客题目——链表的回文结构
39 0
【数据结构OJ题】链表的回文结构