55-链表中环的入口节点

链表

一 题目

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

二 思路

非常详细的方法介绍:博客链接https://cuijiahua.com/blog/2018/01/basis_55.html

C++:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
private:
    //使用快慢指针,判断链表中是否存在环,如果存在,先找出必定存在于环中的一个节点(不一定是入口节点)
    ListNode* MeetingNode(ListNode* pHead){
        ListNode* pSlow = pHead->next;//初始化慢指针,相对于头结点走一步
        if(pSlow == NULL){//节点每走一步需要判断是否为空
            return NULL;
        }
        ListNode* pFast = pSlow->next;//初始化快指针,让它相对于头节点走两步
        while(pFast != NULL && pSlow != NULL){
            if(pFast == pSlow){
                return pFast; 
            }
            pSlow = pSlow->next;
            pFast = pFast->next;//快指针每走一步,判断是否为空
            if(pFast != NULL){
                pFast = pFast->next;//第二步
            }
        }
        return NULL;
    } 
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead == NULL){//空链表
            return NULL;
        }
        //1、使用快慢指针判断链表中是否存在环,若存在,找出环中的任意一个节点
        ListNode* meetingnode = MeetingNode(pHead); 
        if(meetingnode == NULL){//不存在环
            return NULL;
        }
        //2、存在环,找出环中节点个数
        int nodesloop = 1;//初始化
        ListNode* pNode1 = meetingnode;//定义指针指向环中的某个节点(上述找到的)
        while(pNode1->next != meetingnode){
            pNode1 = pNode1->next;
            nodesloop++;
        }
        //3、使用双指针找到环的入口节点(与找链表倒数第K个节点的方法相同)
        pNode1 = pHead;//初始化第一个指针指向头结点
        //第一个指针先向前移动nodesloop步
        for(int i=0; i<nodesloop; i++){
            pNode1 = pNode1->next;
        }
        //两个指针同时移动,相遇时的节点即为环的入口节点
        ListNode* pNode2 = pHead;//初始化第二个指针指向头结点
        while(pNode2 != pNode1){
            pNode1 = pNode1->next;
            pNode2 = pNode2->next;
        }
        return pNode1;
    }
};

python:

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def NodeMeeting(self, pHead):
        #初始化慢指针
        pSlow = pHead.next
        if pSlow == None:
            return None
        #初始化快指针
        pFast = pSlow.next
        while pFast != None and pSlow != None:
            if pFast == pSlow:
                return pFast#相遇的节点必存在于环中
            pSlow = pSlow.next;#慢指针走一步
            pFast = pFast.next.next#快指针走两步(每走一步判断是否为空)
        return None
    
    def EntryNodeOfLoop(self, pHead):
        #空链表
        if pHead == None:
            return None
        #1、使用快慢指针判断链表中是否存在环,存在则继续找出环中的任一个节点,否则返回None
        nodemeeting = self.NodeMeeting(pHead)
        if nodemeeting == None:
            return None
        #2、找出环中节点个数
        nodesloop = 1
        pNode1 = nodemeeting
        while pNode1.next != nodemeeting:
            pNode1 = pNode1.next
            nodesloop += 1
        #3、使用双指针找到环的入口节点
        pNode1 = pHead#初始化第一个指针指向头
        for i in range(nodesloop):#先走nodesloop步
            pNode1 = pNode1.next
        pNode2 = pHead#初始化第二个节点
        while pNode1 != pNode2:
            pNode1 = pNode1.next
            pNode2 = pNode2.next
        return pNode1
        

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值