日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

链表中环的入口结点 python_链表中环的入口结点

發布時間:2025/3/20 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 链表中环的入口结点 python_链表中环的入口结点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

117

推薦

編輯于 2015-08-25 11:27:14

回復(43)

287

思路:

設置快慢指針,都從鏈表頭出發,快指針每次走兩步,慢指針一次走一步,假如有環,一定相遇于環中某點(結論1)。接著讓兩個指針分別從相遇點和鏈表頭出發,兩者都改為每次走一步,最終相遇于環入口(結論2)。以下是兩個結論證明:

兩個結論:

1、設置快慢指針,假如有環,他們最后一定相遇。

2、兩個指針分別從鏈表頭和相遇點繼續出發,每次走一步,最后一定相遇與環入口。

證明結論1:設置快慢指針fast和low,fast每次走兩步,low每次走一步。假如有環,兩者一定會相遇(因為low一旦進環,可看作fast在后面追趕low的過程,每次兩者都接近一步,最后一定能追上)。

證明結論2:

設:

鏈表頭到環入口長度為--a

環入口到相遇點長度為--b

相遇點到環入口長度為--c

則:相遇時

快指針路程=a+(b+c)k+b ,k>=1? 其中b+c為環的長度,k為繞環的圈數(k>=1,即最少一圈,不能是0圈,不然和慢指針走的一樣長,矛盾)。

慢指針路程=a+b

快指針走的路程是慢指針的兩倍,所以:

(a+b)*2=a+(b+c)k+b

化簡可得:

a=(k-1)(b+c)+c 這個式子的意思是: 鏈表頭到環入口的距離=相遇點到環入口的距離+(k-1)圈環長度。其中k>=1,所以k-1>=0圈。所以兩個指針分別從鏈表頭和相遇點出發,最后一定相遇于環入口。 C++版:

class Solution {

public:

ListNode* EntryNodeOfLoop(ListNode* pHead)

{

ListNode*fast=pHead,*low=pHead;

while(fast&&fast->next){

fast=fast->next->next;

low=low->next;

if(fast==low)

break;

}

if(!fast||!fast->next)return NULL;

low=pHead;//low從鏈表頭出發

while(fast!=low){//fast從相遇點出發

fast=fast->next;

low=low->next;

}

return low;

}

}; java版:

public class Solution {

public ListNode EntryNodeOfLoop(ListNode pHead)

{

ListNode fast=pHead;

ListNode low=pHead;

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

fast=fast.next.next;

low=low.next;

if(fast==low)

break;

}

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

return null;

low=pHead;

while(fast!=low){

fast=fast.next;

low=low.next;

}

return low;

}

}

編輯于 2019-12-04 12:29:55

回復(46)

336

【轉】

http://kekecv.com/2016/06/08/Linked-List-Cycle-%E5%88%A4%E6%96%AD%E9%93%BE%E8%A1%A8%E6%98%AF%E5%90%A6%E6%9C%89%E7%8E%AF%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%9C%89%E7%8E%AF%EF%BC%8C%E6%89%BE%E5%88%B0%E7%8E%AF%E7%9A%84%E5%85%A5%E5%8F%A3/

假設x為環前面的路程(黑色路程),a為環入口到相遇點的路程(藍色路程,假設順時針走), c為環的長度(藍色+橙色路程)

當快慢指針相遇的時候:

此時慢指針走的路程為Sslow =

x + m * c + a

快指針走的路程為Sfast = x + n * c + a

2 Sslow =

Sfast

2 * ( x + m*c + a ) = (x + n *c + a)

從而可以推導出:

x = (n

- 2 * m )*c - a

= (n - 2 *m -1 )*c + c - a

即環前面的路程 =

數個環的長度(為可能為0) + c - a

什么是c - a?這是相遇點后,環后面部分的路程。(橙色路程)

所以,我們可以讓一個指針從起點A開始走,讓一個指針從相遇點B開始繼續往后走,

2個指針速度一樣,那么,當從原點的指針走到環入口點的時候(此時剛好走了x)

從相遇點開始走的那個指針也一定剛好到達環入口點。

所以2者會相遇,且恰好相遇在環的入口點。

最后,判斷是否有環,且找環的算法復雜度為:

時間復雜度:O(n)

空間復雜度:O(1)

下面的是斷鏈法。不過題目要求不允許修改鏈表時就尷尬了。

編輯于 2017-03-11 10:47:33

回復(67)

379

第一步,找環中相匯點。分別用p1,p2指向鏈表頭部,p1每次走一步,p2每次走二步,直到p1==p2找到在環中的相匯點。

第二步,找環的入口。接上步,當p1==p2時,p2所經過節點數為2x,p1所經過節點數為x,設環中有n個節點,p2比p1多走一圈有2x=n+x;

n=x;可以看出p1實際走了一個環的步數,再讓p2指向鏈表頭部,p1位置不變,p1,p2每次走一步直到p1==p2;

此時p1指向環的入口。

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;

}

}

發表于 2015-09-15 15:23:04

回復(65)

65

HashSet set = new HashSet();

while (pHead != null) {

if (!set.add(pHead)) {

return pHead;

}

pHead = pHead.next;

}

returnnull;

發表于 2015-10-07 12:45:55

回復(34)

32

//左神講的

//先說個定理:兩個指針一個fast、一個slow同時從一個鏈表的頭部出發

//fast一次走2步,slow一次走一步,如果該鏈表有環,兩個指針必然在環內相遇

//此時只需要把其中的一個指針重新指向鏈表頭部,另一個不變(還在環內),

//這次兩個指針一次走一步,相遇的地方就是入口節點。

//這個定理可以自己去網上看看證明。

public class Solution {

public ListNode EntryNodeOfLoop(ListNode pHead){

ListNode fast = pHead;

ListNode slow = pHead;

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

fast = fast.next.next;

slow = slow.next;

if(fast == slow)

break;

}

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

return null;

fast = pHead;

while(fast != slow){

fast = fast.next;

slow = slow.next;

}

return fast;

}

}

發表于 2017-08-17 11:29:22

回復(13)

114

/*

時間復雜度為O(n),兩個指針,一個在前面,另一個緊鄰著這個指針,在后面。

兩個指針同時向前移動,每移動一次,前面的指針的next指向NULL。

也就是說:訪問過的節點都斷開,最后到達的那個節點一定是尾節點的下一個,

也就是循環的第一個。

這時候已經是第二次訪問循環的第一節點了,第一次訪問的時候我們已經讓它指向了NULL,

所以到這結束。

*/

class Solution {

public:

ListNode* EntryNodeOfLoop(ListNode* pHead)

{

if (!pHead->next)

return NULL;

ListNode* previous = pHead;

ListNode* front = pHead ->next;

while (front)

{

previous->next = NULL;

previous = front;

front = front->next;

}

return previous;

}

};

編輯于 2016-01-26 16:36:01

回復(39)

15

class Solution {

public:

ListNode* EntryNodeOfLoop(ListNode* pHead)

{

set s;

ListNode* node = pHead;

while(node!=NULL){

if(s.insert(node).second)

node = node->next;

else

return node;

}

return node;

}

};

我這里用到了STL中的set,set有一個特性就是不能插入相同元素,這樣只需遍歷原List一次就可以判斷出有沒有環,還有環的入口地址。s.insert(node).second這里在插入的同時也判斷了插入是否成功,如果不成功表明set中已經有該元素了,該元素就是環的入口元素。

發表于 2016-07-23 18:20:48

回復(7)

30

python solution: # -*- coding:utf-8 -*-

# class ListNode:

# def __init__(self, x):

# self.val = x

# self.next = None

class Solution:

def EntryNodeOfLoop(self, pHead):

# write code here

slow,fast=pHead,pHead

while fast and fast.next:

slow=slow.next

fast=fast.next.next

if slow==fast:

slow2=pHead

while slow!=slow2:

slow=slow.next

slow2=slow2.next

return slow

發表于 2017-10-07 19:25:27

回復(14)

24

思路:leetcode上也有這道題,具體思想是,兩個指針fast和slow,fast以slow兩倍速度前進,

如果沒有環,那么fast和slow不會相遇此時返回null;如果有環,那fast和slow肯定會再次相遇

相遇的時候,fast剛好比slow多走了一圈環的長度。

用圖來描述下,當fast與slow相遇時,fast走過的距離為a + b + c + b,而slow走過的距離為

a + b,因為fast是slow速度的兩倍,則有a+b+c+b = 2*(a+b),登出a=c;此時slow節點所處X處

到環起點Y處的距離a和X節點到Y處距離c其實是相等的,此時第三個指針p從x處,以和slow指針

相同的速度前進,當它兩相遇時,即為環的起點Y處!

public class Solution {

public ListNode EntryNodeOfLoop(ListNode pHead)

{

ListNode fast = pHead;

ListNode slow = pHead;

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

fast = fast.next.next;

slow = slow.next;

if(fast == slow) {

ListNode p = pHead;

while( p != slow) {

p = p.next;

slow = slow.next;

}

return p;

}

}

return null;

}

}

編輯于 2017-05-18 13:02:17

回復(9)

13

要尋找環的入口節點,遍歷節點的時候,遇到的第一個重復節點肯定入環節點,所以定義一個Set,

添加失敗時 即返回入口節點

import java.util.*;

public class Solution {

public ListNode EntryNodeOfLoop(ListNode pHead)

{

if(pHead==null)

return null;

ListNode pNode=pHead;

HashSet pSet = new HashSet();

while(pNode!=null){

if(!pSet.add(pNode))

return pNode;

pNode=pNode.next;

}

return null;

}

}

發表于 2016-06-18 10:34:08

回復(6)

8

class Solution:

def EntryNodeOfLoop(self, pHead):

# write code here

linkls = []

while pHead:

if pHead in linkls:

return pHead

linkls.append(pHead)

pHead = pHead.next

return None

發表于 2018-07-05 19:59:29

回復(13)

5

先貼代碼,再解釋; public ListNode EntryNodeOfLoop(ListNode pHead)

{

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

return null;

//step1 發現環

ListNode walk = pHead, run = pHead;

do {

walk = walk.next;

run = run.next.next;

} while (walk != run);

//step2 找到了環,并且run正在環內

//另起一個quickWalk從pHead開始走,quickWalk和run再次相遇的地點就是環的入口

ListNode quickWalk = pHead;

while (quickWalk != run) {

run = run.next.next;

quickWalk = quickWalk.next.next;

}

return quickWalk;

}

}第一步發現環,并找到了walk指針和run指針相遇的地點

第二步另起一個quickWalk指針,和run指針保持同步,倆指針相遇點即為入口;

解釋:

如圖,每個距離的含義: S:環入口到walk和run相遇點的距離

L:walk和run相遇點到入口的距離

P:頭結點到環入口的距離

設walk的速度是v,則run的速度是2v;

設相遇花費了t時間,walk走過的路程為Swalk

根據題意有: 2vt - vt = vt,

又相遇的時候:vt = k(S+L)--①成立;

且 Swalk = vt = P + m(S+L) + S--②成立;

由①②可得 k(S+L) = P + m(S+L) + S

變形為:P = (k-m-1)(S+L) + L。

設 q = (k-m-1),最終得到 P = q(S+L) + L。

因此分別從相遇地點、頭結點同時以相同的速度走的倆指針,最終相遇地點一定是環的入口。

PS:最后兩個同步指針的速度應該是越快越好,因此,采用另起一個quickWalk指針和run同步,而不是和walk同步。

編輯于 2017-12-18 15:45:35

回復(1)

4

public class Solution {

public ListNode EntryNodeOfLoop(ListNode pHead) {

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

ListNode slow = pHead;

ListNode fast = pHead;

while (fast != null) {

fast = fast.next.next;

slow = slow.next;

if(fast == slow) break;

}

fast = pHead;

while (fast != slow) {

fast = fast.next;

slow = slow.next;

}

return slow;

}

}

發表于 2017-04-26 15:38:04

回復(0)

6

'''

解法:

第一步,先找到環中的一個節點(找到之后就可以計算出環中的節點數目)

讓一個指針fast走快一點,一個指針slow走慢一點;當fast與slow相遇時,即fast比slow多一圈,此時相遇的節點肯定是環內的節點

第二步,根據環中的節點來計算環中節點總數

從此節點遍歷到此節點結束,即可得到節點總數

第三步,知道了環內節點總數,來找到環入口

先讓一個指針p1從根節點開始往后走m步,然后再讓一個節點p2指向頭結點;

然后讓p1和p2同時往后移動,當p1與p2相交時,此時的點就是環的入口節點

'''

class Solution:

def EntryNodeOfLoop(self, pHead):

# write code here

meet_node = self.MeetNode(pHead)

if meet_node == None:

return None

# 得到環中的節點個數

loop_nodes = 1

p1 = meet_node

while p1.next != meet_node:

loop_nodes += 1

p1 = p1.next

# 目前已經得到了環中節點個數m,和環中個一個節點meetnode,如何找到環的入口?

# 一個指針p1從根節點開始往后走m步,然后再讓一個節點p2指向頭結點,p1和p2同時往后移動,當p1與p2相交時,此時的點就是環的入口節點

p1 = pHead

for i in range(loop_nodes):

p1 = p1.next

p2 = pHead

while p1 != p2:

p1 = p1.next

p2 = p2.next

return p1

def MeetNode(self, pHead):

if pHead == None:

return None

slow = pHead.next

if slow == None:

return None

fast = slow.next

while slow != None and fast != None:

if slow == fast:

return slow

slow = slow.next

fast = fast.next

if slow != fast:

fast = fast.next

return None

編輯于 2018-05-19 14:52:05

回復(3)

6

//時間復雜度:O(n),用map對訪問過的節點做標記,這樣如果訪問一個節點兩次,表明找到了環入口,否則沒有環。 表示map好好用啊~~

class EntryNodeOfLoop

{

public:

ListNode* EntryNodeOfLoop_Solution(ListNode* pHead)

{

if(pHead==nullptr) return nullptr;

ListNode *ptmp=pHead;

map mlist; //用map關聯各個鏈表指針和對應的映射值

while(ptmp!=nullptr && mlist[ptmp]!=1)

{

mlist[ptmp]=1;//訪問過該鏈表節點,就將實值改為1

ptmp=ptmp->next;

}

if(ptmp==nullptr) return nullptr; //沒有環

else return ptmp; //入口節點

}

};

發表于 2017-05-22 22:29:30

回復(3)

6

劍指offer 上面提到了一種很巧妙的方法:

1. 知道環的長度 len

2. 讓一個結點先走 len 然后讓另一個 和先走的那個一起走,兩者必然會相遇。

問題歸結為,計算len.

整體流程:

1. 用快慢指針求相遇的結點(如果不存在相遇的結點,返回null 不用后面的計算)

2. ?求len

3. 求入口節點。

我們這里使用HashMap , 效率比 ArrayList 效率高點。

/*

public class ListNode {

int val;

ListNode next = null;

ListNode(int val) {

this.val = val;

}

}

*/

import java.util.HashMap;

public class Solution {

public ListNode EntryNodeOfLoop(ListNode pHead){

ListNode node = pHead;

HashMap map = new HashMap<>();

while(node!=null){

if(map.containsKey(node)){

return node;

}else{

map.put(node,true);

node = node.next;

}

}

return null;

}

}

發表于 2016-06-01 16:31:14

回復(3)

2

class?Solution:

def?EntryNodeOfLoop(self,?pHead):

a?=?[]

cur?=?pHead

while?cur:

if?cur?not?in?a:

a.append(cur)

cur?=?cur.next

else:

return?cur

return

發表于 2020-02-29 09:54:31

回復(0)

2

# 這樣把經過的節點記錄下來就可以了呀 class Solution:

def EntryNodeOfLoop(self, pHead):

l = []

p = pHead

res = None

while p:

if p in l:

res = p

break

l.append(p)

p = p.next

return res

編輯于 2019-07-18 09:08:16

回復(1)

2

package entryNodeOfLoop;

import java.util.HashSet;

public class Solution {

public ListNode EntryNodeOfLoop(ListNode pHead) {

if (pHead == null) {

return null;

}

ListNode p = pHead;

HashSet set = new HashSet<>();

while (set.add(p)) {

if (p.next != null) {

p = p.next;

} else {

return null;

}

}

return p;

}

}

發表于 2018-03-10 21:29:48

回復(0)

2

//快慢指針。題目中明明說了有環??墒菫楹芜€要判斷下?

class Solution {

public:

ListNode* EntryNodeOfLoop(ListNode* pHead)

{

ListNode *slow = pHead;

ListNode *fast = pHead;

do{

if(fast == NULL || fast->next==NULL)

return NULL;

fast = fast->next->next;

slow = slow->next;

}while(slow != fast);

slow = pHead;

while(slow != fast){

slow = slow->next;

fast = fast->next;

}

return slow;

}

};

發表于 2017-06-07 14:48:40

回復(4)

總結

以上是生活随笔為你收集整理的链表中环的入口结点 python_链表中环的入口结点的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。