链表
一 题目
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出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