链表的回文结构(链表的中间节点+反转链表)

要解决链表的回文结构:首先需要求中间节点,其次是会反转链表。

一.链表的中间节点

链表的中间节点
在这里插入图片描述

思路1:暴力求解

  1. 求出链表的长度。
  2. 求出要返回的中间节点的位置(除2+1),遍历链表返回节点指针即可。
  3. 注意:兼容奇数个节点与偶数个节点。
typedef struct ListNode ListNode;

struct ListNode* middleNode(struct ListNode* head) 
{
    ListNode* cur = head;
    int listLength = 0; 
    while(cur)
    {
        //求链表的长度
        listLength++;
        cur = cur->next;
    }
    //链表中间节点的位置
    int middle = listLength / 2 + 1;
    int i = 1; //注意:非i=0
    cur = head;
    while(i < middle)
    {
        i++;
        cur = cur->next;
    }
    return cur;
}

思路2:快慢指针

  1. 定义两个指针fast、slow保存链表头节点的地址。
  2. 进入循环,fast指针一次走两个节点,slow指针一次走一个节点,当fast != NULL && fast->next != NULL时循环继续,否则循环结束。

情况1.含有奇数个节点
在这里插入图片描述

情况2.含有偶数个节点

在这里插入图片描述

typedef struct ListNode ListNode;

struct ListNode* middleNode(struct ListNode* head)
{
    //快慢指针:慢指针一次走一步,快指针一次走两步
    ListNode* fast = head;
    ListNode* slow = head;
    //注意循环继续的条件是&&而不是||,且fast与fast->next的位置不能交换
    while (fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

二.返回倒数第k个节点

返回倒数第k个节点

在这里插入图片描述

思路1:暴力求解

  1. 遍历链表求链表的长度length
  2. 倒数第k个节点,等价于从前往后的第length - k个节点。
  3. 再次遍历链表找到第length - k个节点,返回节点指针即可。

在这里插入图片描述

typedef struct ListNode ListNode;

int kthToLast(struct ListNode* head, int k)
{
    //1.遍历链表求出链表长度,再遍历一次链表,找到返回值
	int size = 0;
    ListNode* cur = head;
    while(cur)
    {
        size++;
        cur = cur->next;
    }
    int i = 0;
    cur = head;
    while(i < size - k)
    {
        cur = cur->next;
        i++;
    }
    return cur->val;
}

思路2:快慢指针

  1. 定义两个指针fast、slow保存链表头节点的地址。
  2. fast指针先走k个节点
  3. 进入循环,fast与slow指针各自每次走一个节点,当fast != NULL时循环继续,否则循环结束。

在这里插入图片描述

typedef struct ListNode ListNode;

int kthToLast(struct ListNode* head, int k)
{
	//2.快慢指针:快指针先走k步,然后快指针一次走一步,慢指针一次走一步
    ListNode* fast = head;
    ListNode* slow = head;

    for (int i = 0; i < k; i++)
    {
        fast = fast->next;
    }
    while (fast != NULL)
    {
        fast = fast->next;
        slow = slow->next;
    }
    return slow->val;
}

三.反转链表

反转链表

思路1:头插法

  1. 创建新链表 newHead = NULL。
  2. 遍历原链表,逐个节点头插倒新链表中。

在这里插入图片描述

typedef struct ListNode ListNode;

struct ListNode* reverseList(struct ListNode* head) 
{
    //1.创建新链表,遍历原链表,逐个头插
    ListNode* newHead = NULL, *cur = head;
    while(cur)
    {
        //头插
        ListNode* next = cur->next;
        cur->next = newHead;
        newHead = cur;
        cur = next;
    }
    return newHead;
}

思路2:反转指针的指向

在这里插入图片描述

typedef struct ListNode ListNode;

struct ListNode* reverseList(struct ListNode* head) 
{
	//2.创建三个指针,反转指针的指向
    if(head == NULL)
    {
        return NULL;
    }
    ListNode* n1 = NULL, *n2 = head, *n3 = n2->next;
    while(n2)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n3 != NULL)
        {
            n3 = n3->next;
        }   
    }
    return n1;
}
    

四.链表的回文结构

链表的回文结构

思路1:利用数组,判断是否回文

class PalindromeList {
public:
    //判断数组是否满足回文结构
    bool isReverse(int arr[], int left, int right)
    {
        while(left < right)
        {
            if(arr[left] != arr[right])
            {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
    bool chkPalindrome(ListNode* A)
    {
        int arr[900];
        ListNode* cur = A;
        int i = 0, listLength = 0;
        while(cur)
        {
            arr[i++] = cur->val;//将链表中的值保存到数组中
            cur = cur->next;
            listLength++;//求链表的长度
        }
        return isReverse(arr, 0, listLength - 1);
    }
};

思路2:求链表的中间节点+反转链表

  1. 寻找链表的中间节点 mid。
  2. 将中间节点 mid 以及之后的节点组成的链表反转。
  3. 遍历反转后的链表,当一个一个与原链表的数据域对比,若相同则是回文结构。

情况1.含有奇数个节点:
在这里插入图片描述
情况2.含有偶数个节点:

在这里插入图片描述

class PalindromeList {
public:
    ListNode* findMidNode(ListNode* phead)
    {
        ListNode* fast = phead;
        ListNode* slow = phead;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }
    ListNode* reverseList(ListNode* phead)
    {
        ListNode* n1, *n2, *n3;
        n1 = NULL, n2 = phead, n3 = n2->next;
        while(n2)
        {
            n2->next = n1;
            n1 = n2;
            n2 = n3;
            if(n3 != NULL)
            {
                n3 = n3->next;
            }         
        }
        return n1;
    }
    bool chkPalindrome(ListNode* A) 
    {
        //1.找链表的中间节点
        ListNode* mid = findMidNode(A);
        //2.反转中间节点以及之后的节点组成的链表
        ListNode* right = reverseList(mid);
        //3.遍历反转链表,与原链表进制值的比较
        ListNode* left = A;
        while(right)
        {
            if(right->val != left->val)
            {
                return false;
            }
            right = right->next;
            left = left->next;
        }
        return true;
    }
};
  • 66
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 46
    评论
要验链表是否为回文链表,可以采用以下方法: 1. 使用快慢指针找到链表的中点。 2. 将链表的后半部分反转。 3. 将链表的前半部分与反转后的后半部分进行逐一比较,如果存在不相等的节点,则该链表不是回文链表。 4. 如果链表的所有节点都比较完毕,且没有找到不相等的节点,则该链表是回文链表。 具体操作步骤如下: 1. 初始化快慢指针,快指针每次移动两个节点,慢指针每次移动一个节点,直到快指针到达链表末尾。此时慢指针指向链表的中点。 2. 将链表的后半部分反转。可以使用一个新的指针从慢指针位置开始反转,每次将当前节点的next指针指向前一个节点,然后将指针向后移动一个节点,直到到达链表末尾。最后将反转后的链表的头节点保存下来。 3. 分别使用两个指针,一个指向链表的头节点,另一个指向反转后的链表的头节点。逐一比较两个指针指向的节点的值是否相等,如果存在不相等的节点,则该链表不是回文链表。 4. 如果链表的所有节点都比较完毕,且没有找到不相等的节点,则该链表是回文链表。 通过以上方法,我们可以检验链表是否为回文链表。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++数据结构算法之判断一个链表是否为回文结构的方法](https://download.csdn.net/download/weixin_38737980/14866827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [判断链表是否为回文链表leetcode-LeetCodeAlgorithm:算法问题](https://download.csdn.net/download/weixin_38660295/19945543)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [判断链表是否为回文链表leetcode-LeetCode:力码](https://download.csdn.net/download/weixin_38600696/19945643)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值