栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Leetcode——环形链表

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Leetcode——环形链表

题目原型:

环形链表1:

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

 

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

来源:力扣(LeetCode)

思路:

利用快慢指针的思想,起初二者均指向头指针,慢指针走一步,快指针走两步,这样的话快指针要比满指针先入环,如果没有环的话,那样满指针永远都不会追上慢指针;但如果有环的话,慢指针终究会追上快指针。

具体代码如下:

typedef struct ListNode node;
bool hasCycle(struct ListNode *head)
{
    node* fast=head;
    node* slow=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        return true;
    }
    return false;
}

但此时一定会有人有疑问,为什么快指针非要走两步,如果是走三步、四步呢?

一.如果是走两步

假设slow进入圈后,slow与fast的距离为N,那么slow与fast之间的距离就会减少1,以此类推,最后二者就会相遇。

二.如果是走三步

此时fast一次三步,slow一次走两步,二者之间距离会减少2,,当N为偶数时,二者一定会追上;如果N为奇数时,二者的距离到最后的距离会变为-1,那么他们的距离就会变为环的大小减1,那么二者终究不会相遇。

题目原型:

环形链表2:

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

 

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

来源:力扣(LeetCode)

思路一:

首先我们要知道,慢指针进入环后,快指针一定在一圈之内追上了慢指针,只是为什么呢?

因为如果慢指针走了一圈,哪末快指针一定已经走了两圈,所以二者不可能错过,即慢指针最多走半圈,快指针就追上来了。

假设环外的长度为L,环内慢指针走的路程为X,哪样慢指针走的路程为L+X,哪快指针走的路程为多少呢?

则快指针走的路程为L+kC+X,C为环的长度,k为慢指针未进入环前快指针绕环的圈数,有上述条件我们知道快指针走的路程为慢指针的两倍,,所以有以下方程:2*(L+X)=L+k*C+X,化解有:

L=k*C-X

由此方程可知一个指针从头结点出发,另一个指针从快慢指针相遇位置出发,那么二者会相遇于入环的位置,由此思路便可开始编写代码。

具体代码如下:

typedef struct ListNode node;
struct ListNode *detectCycle(struct ListNode *head) 
{
    node* fast=head;
    node* slow=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            node* meet=slow;
            while(meet!=head)
            {
                meet=meet->next;
                head=head->next;
            }
            return meet;
        }
    }
   
    return NULL;
}

思路二:

利用相交链表的思想,将此链表分为两个链表,二者相交的节点即为进入节点的位置,第一个链表为以快慢指针为头结点,第二个链表为以慢指针下一个节点为头节点的链表。

具体代码如下:

typedef struct ListNode node;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    node* curA=headA;
    int countA=0;
    while(curA)
    {
        curA=curA->next;
        countA++;
    }
    node* curB=headB;
    int countB=0;
    while(curB)
    {
        curB=curB->next;
        countB++;
    }
    node* longlist=headA;
    node* shortlist=headB;
    if(countAnext;
    }
    while(longlist)
    {
        if(longlist==shortlist)
        return longlist;
        longlist=longlist->next;
        shortlist=shortlist->next;
    }
    return NULL;
}

node *detectCycle(node *head) 
{
    node* fast=head;
    node* slow=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            node* meet=slow;
            node* newcode=slow->next;
            meet->next=NULL;  
            return getIntersectionNode(head,newcode);          
        }
       
    }
   
    return NULL;
}
希望文章对您有帮助!!!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/879405.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号