bfs(breath first search)和dfs(depth first search) 是兩種十分常用的演算法,其中dfs演算法可以認為是回溯演算法
bfs演算法和核心就是將問題抽象成圖,從一點開始進行擴散,一般來說寫bfs的時候均使用佇列,每次將乙個結點周圍的所有結點加入到佇列中
bfs相對於dfs的主要區別是:bfs找到的路徑一定是最短的,但代價是空間複雜度比dfs高
func
bfs(start node, target node)
// 否則如果其相鄰結點沒有被訪問過就加入到佇列中
for_
, i :=
range n.adjacency }}
// 又訪問了一層
step++
}}
佇列
是bfs中的核心資料結構,n.adjacency泛指與結點相鄰的其他結點
,visited作用是為了防止走回頭路,大部分的時候是需要的,但是對於類似一般的二叉樹結構,沒有子節點到父結點的指標,不會走回頭路就不需要使用visited進行標記
輸入乙個二叉樹,計算它的最小高度,也就是根節點到葉子結點的短距離
那麼這道題應該如何套用bfs呢?該題中的開始結點為start,終點就是最靠近根節點的葉子結點,也就是左子樹為nil,右子樹也為nil
func
getminheight
(root *node)
int// 假設宣告乙個佇列
var q queue
// 將根節點加入到佇列中
q.push
(root)
depth :=
1for
!q.empty()
// 左節點
if n.left !=
nil// 右結點
if n.right !=
nil}
// 增加一層深度
depth ++
}return depth
}
當然其實求解二叉樹的最大高度也可以使用bfs進行求解,我們只要將佇列中的資料全部遍歷完,這樣我們肯定就遍歷了最後一層結點,題目可見 leetcode
下面是**:
func
maxdepth
(root *treenode)
int q :=
make([
]*treenode,1)
q[0]
= root
count :=
0for
len(q)
>
0if n.right !=
nil}
count ++
}return count
}
在**複雜問題之前,先回答下面的兩個問題:
1. 為什麼bfs可以找到最短距離,但是dfs不行?
在bfs中,只有當每乙個結點都向下移動一步的時候,才會使得depth加一,所以可以保證一旦找到乙個終點,那麼所需要的步數是最小的,bfs最壞的時間複雜度為o(n
)o(n)
o(n)
。dfs同樣可以求解這類問題,但是需要遍歷所有的路徑才能找到最短的路徑,雖然說dfs在big o衡量標準下最壞的時間複雜度都是o(n
)o(n)
o(n)
,但是bfs更加高效,我們可以認為,在求解的過程中,bfs走的是線,而dfs走的是點。
2. 既然bfs這麼好,那麼為啥要使用dfs?
bfs可以找到最短距離,但是空間複雜度相對而言比較高,而dfs的空間複雜度較低
一般而言,在求解最短路徑的時候使用bfs,其他時候更多的使用bfs
leetcode 752題
我們可以每乙個密碼看出乙個結點,每乙個密碼進行變化之後可以衍生出其他的不同密碼,乙個結點可以連線到其他另外8個頂點,整個求解過程就是乙個圖的遍歷問題,我們要想獲取到最小的次數,那麼可以使用bfs來進行求解。
在這個題目中,開始結點就是0000
,而終點就是所給的target,但是這個不想二叉樹,有可能會走回頭路,所以需要使用visited進行
**如下
func
openlock
(deadends [
]string
, target string
)int
if cur == target
for i :=
0; i <
4; i++
d :=
down([
]byte
(cur)
, i)
if!visited[d]}}
count++
}return-1
}func
isdead
(deadends [
]string
, lock string
)bool
}return
false
}// 向上撥動一格
func
up(s [
]byte
, i int
)string
else
return
string
(s)}
// 向下撥動一格
func
down
(s [
]byte
, i int
)string
else
return
string
(s)}
這道題還可以使用雙向bfs進行求解,具體見: bfs框架,這裡不做講 第一章 核心套路篇 之 滑動視窗演算法框架
滑動視窗演算法的主要 框架如下 s 是所給的字串或者其他陣列 t 是目標值 func slidingwindow s,t string left,right 0,0 valid 0 s不一定是字串,還可以是其他型別的陣列 如果右指標還沒有到達s的終點 for right len s 下面以例子來進行...
第一章 Linux核心簡介
unix 中所有的東西都被當作檔案對待。unix 核心和相關的系統工具軟體是用 c 語言編寫而成。unix 程序建立非常迅速,並且有乙個非常獨特的 fork 系統呼叫。linux 是非商業化的產品,它使用 gnu 的 general public license gpl 第二版本作為限制條款。執行於...
第一章 Linux核心簡介
1.linux是類unix系統,但他不是unix。儘管linux借鑑了unix的許多設計並且實現了unix的api 由posix標準和其他single unix specification定義的 但linux沒有像其他unix變種那樣直接使用unix的原始碼。2.linux系統的基礎是核心 c庫 工...