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

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

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

题目链接

思路

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


相关文章
|
4月前
|
存储 C语言
用指针处理链表
用指针处理链表
44 3
|
1月前
【刷题记录】链表的回文结构
【刷题记录】链表的回文结构
|
2月前
【数据结构OJ题】复制带随机指针的链表
力扣题目——复制带随机指针的链表
48 1
【数据结构OJ题】复制带随机指针的链表
|
1月前
|
Python
【Leetcode刷题Python】138. 复制带随机指针的链表
LeetCode上题目“138. 复制带随机指针的链表”的Python解决方案,包括两种方法:一种是在每个节点后复制一个新节点然后再分离出来形成新链表;另一种是构建一个字典来跟踪原始节点与其副本之间的映射关系,从而处理新链表的构建。
14 1
|
1月前
|
存储 算法 数据处理
指针与链表
指针与链表
52 0
|
1月前
|
Python
【Leetcode刷题Python】234.回文链表
两种判断链表是否为回文的方法:使用栈和拆分为两个链表后反转对比,并给出了相应的Python代码实现。
16 0
|
2月前
【数据结构OJ题】链表的回文结构
牛客题目——链表的回文结构
30 0
【数据结构OJ题】链表的回文结构
|
3月前
|
算法 C语言
【数据结构与算法 经典例题】链表的回文结构(图文详解)
【数据结构与算法 经典例题】链表的回文结构(图文详解)
|
3月前
|
算法
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
|
4月前
题目----力扣--回文链表
题目----力扣--回文链表
31 0