链表中环的入口结点

题目描述

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

思路:找一快一慢两个指针,慢指针一次走一步,快指针一次走两步,然后如果有环会相遇,否则就会变为NULL。然后就有两种想法,一种是找到环的长度,然后找两个指针,一个先走环的长度,另一个从起点出发,相遇的地方就是环的入口。还有两一种更优秀的思路,一快一慢两个指针,假设环外链表长度为a,环的长度为b,相遇点拒环的入口长度为c,那么相遇时满足a+b+c=2*(a+c),然后能得到c=b-a,所以让快指针回到起点,然后每次走一步就能和慢指针在环的入口相遇。

代码:第一份代码是我自己的,第一种思路,然后贴了剑指offer的第一种思路的方法,第三份代码是第二种思路,很简洁。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead==NULL)
            return NULL;
        ListNode* p1=pHead,*p2=pHead;
        while(p1->next!=NULL&&p2->next!=NULL){
            p1=p1->next;
            p2=p2->next;
            if(p2->next!=NULL)
                p2=p2->next;
            if(p1==p2){
                int len = LoopLength(p1);
                ListNode* e = FindEntry(pHead,len);
                return e;
            }
        }
        return NULL;
    }
    int LoopLength(ListNode* p){
        int cou=1;
        ListNode* tem = p->next;
        while(p!=tem){
            cou++;
            tem=tem->next;
        }
        return cou;
    }
    ListNode* FindEntry(ListNode* p,int len){
        ListNode* entry = p;
        for(int i=0;i<len;i++){
            entry=entry->next;
        }
        while(entry!=p){
            entry=entry->next;
            p=p->next;
        }
        return entry;
    }
};

 

链接:https://www.nowcoder.com/questionTerminal/253d2c59ec3e4bc68da16833f79a38e4
来源:牛客网
 

public class 链表中环的入口结点 {

    //找到一快一满指针相遇处的节点,相遇的节点一定是在环中

    public static ListNode meetingNode(ListNode head) {

        if(head==null)

            return null;

         

        ListNode slow = head.next;

        if(slow==null)

            return null;

         

        ListNode fast = slow.next;

        while (slow != null && fast != null) {

            if(slow==fast){

                return fast;

            }

            slow=slow.next;

            fast=fast.next;

             

            if(fast!=slow){

                fast=fast.next;

            }

        }

        return null;

    }

    public ListNode EntryNodeOfLoop(ListNode pHead) {

        ListNode meetingNode=meetingNode(pHead);

        if(meetingNode==null)

            return null;

//      得到环中的节点个数

        int nodesInLoop=1;

        ListNode p1=meetingNode;

        while(p1.next!=meetingNode){

            p1=p1.next;

            ++nodesInLoop;

        }

//      移动p1

        p1=pHead;

        for(int i=0;i<nodesInLoop;i++){

            p1=p1.next;

        }

//      移动p1,p2

        ListNode p2=pHead;

        while(p1!=p2){

            p1=p1.next;

            p2=p2.next;

        }

        return p1;

    }

}

 

链接:https://www.nowcoder.com/questionTerminal/253d2c59ec3e4bc68da16833f79a38e4
来源:牛客网
 

public class Solution {

 

    ListNode EntryNodeOfLoop(ListNode pHead){

        if(pHead == null || pHead.next == null)

            return null;

        ListNode p1 = pHead;

        ListNode p2 = pHead;

        while(p2 != null && p2.next != null ){

            p1 = p1.next;

            p2 = p2.next.next;

            if(p1 == p2){

                p2 = pHead;

                while(p1 != p2){

                    p1 = p1.next;

                    p2 = p2.next;

                }

                if(p1 == p2)

                    return p1;

            }

        }

        return null;

    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值