【LeetCode之链表】:经典的快慢指针相关问题

1. 返回链表的中间结点

LeetCode链接: 【链表的中间结点】
在这里插入图片描述
思路1: 最容易想到的思路是先统计整个链表的结点个数,然后就可以得出中间结点的位置是在第几个,最后再从头结点走到中间结点位置即可。
代码实现如下:

struct ListNode* middleNode(struct ListNode* head){
    int count=0;
    struct ListNode* cur=head;
    //求链表中有多少结点
    while(cur!=NULL)
    {
        count++;
        cur=cur->next;
    }
     //求出中间节点的位置
    count=count/2;

    //找到中间结点
    cur=head;
    while(count--)
    {
        cur=cur->next;
    }
    return cur;

}

思路2: 采用快慢指针法,慢指针走一步,快指针走两步;当快指针的指针域为空指针或者快指针为空指针时就结束,此时慢指针就是中间结点。
过程分析如下:
在这里插入图片描述
代码实现如下:

struct ListNode* middleNode(struct ListNode* head){
    struct ListNode* slow=head;
    struct ListNode* fast=head;
    //有两种情况快指针要停下
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;

}

2. 输出该链表中倒数第k个结点

LeetCode链接: 【22. 链表中倒数第k个节点】
在这里插入图片描述
这道题也是采用两个指针来解决,先让快指针走k步,这样快指针和慢指针的距离就是k步; 然后快指针走一步,慢指针也走一步;当快指针走到空指针时,慢指针还是距离快指针k步;这样慢指针就是倒数第k个结点。
过程分析如下:
在这里插入图片描述
代码实现如下:

struct ListNode* getKthFromEnd(struct ListNode* head, int k){
    struct ListNode* slow=head;
    struct ListNode* fast=head;
    //先让快指针走k步,这样快指针和慢指针的距离就是k步
    while(k--)
    {
        //防止k过大,造成对空指针进行解引用
        if(fast==NULL)
        {
            return NULL;
        }
        fast=fast->next;
    }
    
    //快指针走一步,慢指针也走一步
    //当快指针走到空指针时,慢指针还是距离快指针k步
    //这样慢指针就是倒数第k个结点
    while(fast!=NULL)
    {
        slow=slow->next;
        fast=fast->next;
    }
    return slow;


}

3. 链表的回文结构

LeetCode链接: 【回文链表】

在这里插入图片描述
我们可以观察到回文链表如果以中间结点为对称轴,那么两边的值是一样的;所以我们判断是不是回文链表,先找到中间结点,然后以中间结点为起点把右边的结点给反转过来,这样就可以对比左右两边的结点了,全部相同就是回文链表,如果有一个不相等就不是回文链表。
那么怎么才是全部相同呢?那就是把左右链表遍历一遍即可,当任意一边链表走到空了,则说明此链表是回文链表。
过程分析如下:
在这里插入图片描述
代码实现如下:

//求出中间结点
struct ListNode* MidListNode(struct ListNode* head)
{
    struct ListNode* slow=head;
    struct ListNode* fast=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

 //反转链表
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* cur=head;
    struct ListNode* prev=NULL;
    while(cur!=NULL)
    {
        struct ListNode* next=cur->next;
        cur->next=prev;

        prev=cur;
        cur=next;
    }
    return prev;
}


bool isPalindrome(struct ListNode* head){
    //先求出中间结点
    struct ListNode* mid=MidListNode(head);
    //然后以中间结点为开始,反转后面的结点
    struct ListNode* headB=reverseList(mid);
    struct ListNode* headA=head;
    
    //接着开始对比两个链表是否相同
    //不管链表结点是否是奇数还是偶数
    //当任意一个链表走到空时,两个链表内容就全部相等,即是回文链表
    while(headA && headB)
    {
        if(headA->val!=headB->val)
        {
            return false;
        }
        headA=headA->next;
        headB=headB->next;
    }
    return true;

}
  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值