人間算法題:到底是不是一個環?

很多人都說人生就是一個循環,每天重複重複。
而所謂環,對於寫代碼的小夥伴來說是有特殊定義的。我的理解就是節點循環,就成了環。
剛好刷到一個掘金好友分享的騰訊一面算法題:判斷一個單鏈表是不是一個環。
其實有很多辦法來實現,但是我更喜歡用快慢指針來判斷環的形成。思路如下:

  1. 定義一個slow指針,指向單鏈表的頭部節點head。定義一個fast指針,初始化爲head.next。
    2.然後先判斷fast和fast.next是否是空,如果爲空,肯定不是環。
    3.然後開始移動快慢兩個指針。slow指針每次只移動一個節點,fast指針每次移動2個節點。
    4.如果在移動的過程中slow指向的節點等於fast指向的節點,那麼說明循環了,這是一個環。
    5.如果移動到鏈表最後(假設不是環,有尾部)還是沒有slow和fast節點重合,那麼說明不是環。

所謂環,那麼就一定會快慢指針一定會相遇。

那麼用golang實現一下:

package main

import (
    "fmt"
)

type ListNode struct {
   Val int
   Next *ListNode
}
func HasCircle(head *ListNode) bool {
    slow, fast := head, head.Next

    if fast == nil || fast.Next == nil {
        return false
    }

    for fast != nil && fast.Next != nil {
        if slow == fast {
            return true
        }

        slow = slow.Next
        fast = fast.Next.Next
    }

    return false
}

func main() {
    // create the list
    head := &ListNode{Val: 1}
    head.Next = &ListNode{Val: 2}
    head.Next.Next = &ListNode{Val: 3}
    head.Next.Next.Next = &ListNode{Val: 4}
    head.Next.Next.Next = head.Next
    fmt.Println("Is circle? ", HasCircle(head))
}

死去的記憶又在攻擊我了,我想起多年前去一家互聯網醫療公司面試的時候也遇到這道題,我也給出了這個解法,但是面試官一臉懵逼,無法理解我的思路。今天我仔細想想,也許是他想看到我用深度優先搜索(DFS)來實現。
所謂深度優先,就是一種遞歸算法,用於搜索圖或樹數據結構的所有頂點。該算法從起始節點開始,儘可能沿着每條路徑探索,直到無法再前進爲止,然後進行回溯。DFS通常使用堆棧來跟蹤已發現的節點,以便進行回溯。這種算法的時間複雜度爲O(V+E),其中V是頂點數,E是邊數。在實際應用中,DFS還有許多應用,包括尋找連通分量、檢測圖中的環、拓撲排序等。
檢測環,用它就對啦,實現如下所示:

func dfs(node *ListNode, visited map[*ListNode]bool) bool {
    if node == nil {
        return false
    }

    if visited[node] {
        return true
    }

    visited[node] = true

    return dfs(node.Next, visited)
}
func HasCircleByDFS(head *ListNode) bool {
    visited := make(map[*ListNode]bool)
    return dfs(head, visited)
}

func main() {
    // create the list
    head := &ListNode{Val: 1}
    head.Next = &ListNode{Val: 2}
    head.Next.Next = &ListNode{Val: 3}
    head.Next.Next.Next = &ListNode{Val: 4}
    head.Next.Next.Next = head.Next
    fmt.Println("Is circle? ", HasCircleByDFS(head))
}

總結
有時候面試者需要去推測出題人的意圖,條條道路雖然通羅馬,但你的解法不一定能打動考官。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章