方法一:雙重循序遍歷
從頭節點開始,一次遍歷單鏈表的,每一個人節點。沒遍歷一個新節點,就從頭檢查新節點之前的所有節點,用新節點和之前所有的節點一次比較,如果發現和之前的某一個節點相同 ,則說明該節點被遍歷兩次,說明環。
缺點:時間複雜度O(n^2)太高,空間複雜度O(1)
代碼如下
///Swift 鏈表
public class Node {
var data: Int
var next: Node?
init(_ data: Int) {
self.data = data;
}
}
func nodeIsRing(_ node: Node) -> Bool {
var nextNode = node.next
while nextNode != nil {
var proNode = node
while (nextNode! !== proNode) {
if proNode === nextNode?.next {
return true //有相等的就返回true 有環啦
}
proNode = proNode.next!
}
nextNode = nextNode?.next//繼續遍歷下一個
}
return false;
}
方法二:把之前的遍歷的結果實現存儲起來
前邊遍歷的數據都存儲起來,新的節點和之前的對比,如果有相同的這說明就是有環。可以用哈希表,代碼略…
時間複雜度:O(n) 空間複雜度也是O(n)
方法三:如果環形跑道,速度不同時,兩個人一定會相遇。
既然是環,我們用兩個變量,一個增幅是1,一個增幅是二,那麼兩個指針必然會相遇。如果不是環,永遠也不會相遇。
時間複雜度:O(n) 空間複雜度也是O(1)
代碼
func isNodeSpeed(_ node: Node) -> Bool {
var fastNode: Node? = node
var slowNode: Node? = node
while true {
fastNode = fastNode?.next?.next
slowNode = slowNode?.next
if fastNode == nil && slowNode == nil {
return false //不是環
}
if fastNode != nil && slowNode != nil && fastNode === slowNode {
return true //有環
}
}
}
拓展之:如何求出入環點?和 環的長度?
歡迎在下方評論