1.為什麼寫這個隨筆?
前幾天參加乙個電面,被問到這個問題,想總結一下。
2.為什麼標題強調c#?
想在網上看看**,卻沒找到c#版的,於是自己用c#實現一下。
一、解決問題的思路
1.一種比較耗空間的做法是,從頭開始遍歷鍊錶,把每次訪問到的結點存入乙個集合(hashset)或字典(dictionary),如果發現某個結點已經被訪問過了,就表示這個鍊錶存在環,並且這個結點就是環的入口點。
空間複雜度為o(n),時間複雜度為o(n)
2.追趕法:使用兩個slow, fast指標從頭開始掃瞄鍊錶。指標slow 每次走1步,指標fast每次走2步。如果存在環,則指標slow、fast會相遇;如果不存在環,指標fast遇到null退出。
空間複雜度為o(1),時間複雜度為o(n)
僅僅考慮**實現方面第一種方法相對簡單,所以下面用第二種方法來實現。
二、解析(追擊相遇)
給出乙個存在環的單鏈表:1,2,3,4,5,3,4,5...
用圖表示出來:
然後按照追趕法的定義一步一步走:
從上圖可以看出第四次和第七次快慢指標在節點4處相遇,7-4=3,正好是環的長度;
求出環的長度後,我們便可以求出入口點:
鍊錶總長=5;
頭結點到入口點的距離=鍊錶總長-環長;即=5-3=2;
然後從頭結點開始向下遍歷,得到入口點3;
三、**
1.單鏈表節點
12.單鏈表//單鏈表節點
2class linknode3
6public
t data
7
8public
linknode()913
public
linknode(t val)
1418
public linknode(t val,linknodenode)
1923 }
13.測試class dlinkedlist2
5public
intlength
6
7public
dlinkedlist()812
public
void add(linknodenode)//插入節點
1320
else
2127 currentnode.next =node;
28 length++;29}
30}31public
void
display()//顯示鍊錶
3239}40
public
intgetlength()//獲取鍊錶長度
4144
public
bool
isempty()//判空
4548
public
bool
hascircle()//判斷是否有環
4962
catch
(nullreferenceexception)
6367
if (slownode == fastnode && slownode != head && slownode != null)68
");71 count++;72}
73if (count == 1
)//第一次相遇
74 step++;//計步,獲取環長
75if (count == 2
)//第二次相遇76"
);78
break;79
}80}81
getpoint(step);
82return
result;83}
84public linknodegetpoint(int
circlelength)//獲取相交點
8597
}98 console.writeline($"
the meet node's data is ");
99return
currentnode;
100}
101 }
1測試結果如圖:class
program214
list.add(tmp);
15console.writeline(list.hascircle());
16console.readkey();17}
18 }
判斷乙個單鏈表是否有環及環
判斷乙個單鏈表是否有環及環的鏈結點 蒙恩的罪人 給定乙個單鏈表,只給出頭指標h 1 如何判斷是否存在環?2 如何知道環的長度?3 如何找出環的連線點在 4 帶環鍊錶的長度是多少?解法 1 對於問題1,使用追趕的方法,設定兩個指標slow fast,從頭指標開始,每次分別前進1步 2步。如存在環,則兩...
判斷乙個單鏈表是否有環及環入口
要求 不允許修改鍊錶結構 時間複雜度o n 空間複雜度o 1 判斷是否有環 如果鍊錶有環,那麼在遍歷時則會陷入死迴圈。使用快慢指標 快指標移動2步,慢指標移動1步 如果走到某一步,快慢指標相遇,則說明有環 環入口點 我們假設鍊錶頭部到環入口距離 len,環入口到快慢指標交匯點的距離為x,環的長度為r...
判斷乙個單鏈表是否有環
一 判斷鍊錶是否存在環 設定兩個指標 fast,slow 初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入 環,而slow後進入環,兩個指標必定相遇。當然,fast先行頭到尾部為null,則為無環鏈表 程式如下 bool i itsloop listn...