代碼隨想錄二刷之“圖論”~GO

A.深搜與廣搜(重點掌握!!!!)

深搜類似于回溯法

  • 搜索方向,是認準一個方向搜,直到碰壁之后再換方向
  • 換方向是撤銷原路徑,改為節點鏈接的下一個路徑,回溯的過程。

廣搜能保存我們要遍歷過的元素的容器就可以,隊列、棧、數組都是OK

  • 用隊列的話,就是保證每一圈都是一個方向去轉,例如統一順時針或者逆時針。因為隊列是先進先出,加入元素和彈出元素的順序是沒有改變的。
  • 如果用棧的話,就是第一圈順時針遍歷,第二圈逆時針遍歷,第三圈有順時針遍歷。因為棧是先進后出,加入元素和彈出元素的順序改變了

1.可達路徑

感悟:找出從1到5的所有路徑,深度優先搜索的代碼其實和回溯法很像,節點入path,遞歸+回溯

var result [][]int 
var path []int     
func dfs(graph [][]int, x, n int) {// 當前遍歷的節點x 到達節點nif x == n { // 找到符合條件的一條路徑temp := make([]int, len(path))copy(temp, path)result = append(result, temp)return}for i := 1; i <= n; i++ { // 遍歷節點x鏈接的所有節點if graph[x][i] == 1 { // 找到 x鏈接的節點path = append(path, i)    // 遍歷到的節點加入到路徑中來dfs(graph, i, n)          // 進入下一層遞歸path = path[:len(path)-1] // 回溯,撤銷本節點}}
}

2.島嶼數量

方法一:深搜---模板題,后期要總結!!!!

package main
import "fmt"var dir = [][]int{{0, 1},   // 右{1, 0},   // 下{-1, 0},  // 上{0, -1},  // 左
}
func dfs(graph [][]int, visited [][]bool,x,y int){for i := range dir{nextx := x + dir[i][0]nexty := y + dir[i][1]if nextx < 0||nextx >= len(graph)||nexty < 0||nexty >=len(graph[0]){continue}if !visited[nextx][nexty] && graph[nextx][nexty] == 1{visited[nextx][nexty] = truedfs(graph,visited,nextx,nexty)}}
}
func main(){var n,m intfmt.Scan(&n,&m)graph := make([][]int,n)for i := range graph{graph[i] = make([]int,m)}for i := 0;i < n; i++{for j := 0;j < m; j++{fmt.Scan(&graph[i][j])}}visited := make([][]bool,n)for i := range visited{visited[i] = make([]bool,m)}var res intfor i := 0;i < n;i++{for j := 0;j < m;j++{if !visited[i][j] && graph[i][j] == 1{visited[i][j] = trueres++dfs(graph,visited,i,j)//將和他相連的陸地都標記上true}}}fmt.Println(res)
}

方法二:廣搜---模板題---后期要總結!!!

package main
import ("fmt""container/list"
)var dir = [4][2]int{{0, 1},   // 右{1, 0},   // 下{-1, 0},  // 上{0, -1},  // 左
}
func bfs(graph [][]int, visited [][]bool,x,y int){queue := list.New()queue.PushBack([2]int{x,y})visited[x][y] = truefor queue.Len() > 0{cur := queue.Remove(queue.Front()).([2]int)curx,cury := cur[0],cur[1]for i := range dir{nextx := curx + dir[i][0]nexty := cury + dir[i][1]if nextx < 0 || nexty < 0||nextx >= len(graph)||nexty >= len(graph[0]){continue}if !visited[nextx][nexty] && graph[nextx][nexty] == 1{visited[nextx][nexty] = truequeue.PushBack([2]int{nextx,nexty})}}}
}func main(){var n,m intfmt.Scan(&n,&m)graph := make([][]int,n)for i := range graph{graph[i] = make([]int,m)}for i := 0;i < n;i++{for j := 0;j < m;j++{fmt.Scan(&graph[i][j])}}visited := make([][]bool,n)for i := range visited{visited[i] = make([]bool,m)}var res intfor i := 0;i < n;i++{for j := 0;j < m;j++{if !visited[i][j] && graph[i][j] == 1{visited[i][j] = trueres++bfs(graph,visited,i,j)//將和他相連的陸地都標記上true}}}fmt.Println(res)
}

3.島嶼最大面積

感悟:本題就在模板題的基礎之上統計面積!!!

package main
import "fmt"var dir = [][]int{{0, 1},   // 右{1, 0},   // 下{-1, 0},  // 上{0, -1},  // 左
}
var count int
func dfs(graph [][]int, visited [][]bool,x,y int){for i := range dir{nextx := x + dir[i][0]nexty := y + dir[i][1]if nextx < 0||nextx >= len(graph)||nexty < 0||nexty >=len(graph[0]){continue}if !visited[nextx][nexty] && graph[nextx][nexty] == 1{visited[nextx][nexty] = truecount++dfs(graph,visited,nextx,nexty)}}
}
func max(i,j int)int{if i > j{return i}else{return j}
}
func main(){var n,m intfmt.Scan(&n,&m)graph := make([][]int,n)for i := range graph{graph[i] = make([]int,m)}for i := 0;i < n; i++{for j := 0;j < m; j++{fmt.Scan(&graph[i][j])}}visited := make([][]bool,n)for i := range visited{visited[i] = make([]bool,m)}var res intfor i := 0;i < n;i++{for j := 0;j < m;j++{if !visited[i][j] && graph[i][j] == 1{visited[i][j] = truecount = 1dfs(graph,visited,i,j)res = max(res,count)//將和他相連的陸地都標記上true}}}fmt.Println(res)
}

4.孤島總面積

本題要求找到不靠邊的陸地面積,那么我們只要從周邊找到陸地然后 通過 dfs或者bfs 將周邊靠陸地且相鄰的陸地都變成海洋,然后再去重新遍歷地圖 統計此時還剩下的陸地就可以了。

package mainimport ("container/list""fmt"
)// 四個方向的偏移量
var dir = [][]int{{0, 1},   // 右{1, 0},   // 下{-1, 0},  // 上{0, -1},  // 左
}// BFS函數,用于標記并清除連通的陸地
func bfs(grid [][]int, x, y int) {// 使用list作為隊列que := list.New()que.PushBack([2]int{x, y})grid[x][y] = 0 // 加入隊列后立即標記為已訪問// 隊列不為空時繼續處理for que.Len() > 0 {// 取出隊首元素cur := que.Front().Value.([2]int)que.Remove(que.Front())curx, cury := cur[0], cur[1]// 遍歷四個方向for i := 0; i < 4; i++ {nextx := curx + dir[i][0]nexty := cury + dir[i][1]// 邊界檢查if nextx < 0 || nextx >= len(grid) || nexty < 0 || nexty >= len(grid[0]) {continue}// 如果是未訪問的陸地,加入隊列并標記if grid[nextx][nexty] == 1 {que.PushBack([2]int{nextx, nexty})grid[nextx][nexty] = 0 // 加入隊列后立即標記}}}
}func main() {var n, m intfmt.Scan(&n, &m)// 初始化網格grid := make([][]int, n)for i := range grid {grid[i] = make([]int, m)}// 讀取網格數據for i := 0; i < n; i++ {for j := 0; j < m; j++ {fmt.Scan(&grid[i][j])}}// 處理左右邊界的陸地for i := 0; i < n; i++ {if grid[i][0] == 1 {bfs(grid, i, 0)}if grid[i][m-1] == 1 {bfs(grid, i, m-1)}}// 處理上下邊界的陸地for j := 0; j < m; j++ {if grid[0][j] == 1 {bfs(grid, 0, j)}if grid[n-1][j] == 1 {bfs(grid, n-1, j)}}// 統計剩余的陸地(孤島)數量count := 0for i := 0; i < n; i++ {for j := 0; j < m; j++ {if grid[i][j] == 1 {count++}}}fmt.Println(count)
}

5.沉沒孤島

感悟:這道題只不過遇到陸地就加一,最后都減1。和上道題一個思路

package mainimport ("container/list""fmt"
)// 四個方向的偏移量
var dir = [][]int{{0, 1},   // 右{1, 0},   // 下{-1, 0},  // 上{0, -1},  // 左
}// BFS函數,用于標記并清除連通的陸地
func bfs(grid [][]int, x, y int) {// 使用list作為隊列que := list.New()que.PushBack([2]int{x, y})grid[x][y] = 2 // 加入隊列后立即標記為已訪問// 隊列不為空時繼續處理for que.Len() > 0 {// 取出隊首元素cur := que.Front().Value.([2]int)que.Remove(que.Front())curx, cury := cur[0], cur[1]// 遍歷四個方向for i := 0; i < 4; i++ {nextx := curx + dir[i][0]nexty := cury + dir[i][1]// 邊界檢查if nextx < 0 || nextx >= len(grid) || nexty < 0 || nexty >= len(grid[0]) {continue}// 如果是未訪問的陸地,加入隊列并標記if grid[nextx][nexty] == 1 {que.PushBack([2]int{nextx, nexty})grid[nextx][nexty] = 2 // 加入隊列后立即標記}}}
}func main() {var n, m intfmt.Scan(&n, &m)// 初始化網格grid := make([][]int, n)for i := range grid {grid[i] = make([]int, m)}// 讀取網格數據for i := 0; i < n; i++ {for j := 0; j < m; j++ {fmt.Scan(&grid[i][j])}}// 處理左右邊界的陸地for i := 0; i < n; i++ {if grid[i][0] == 1 {bfs(grid, i, 0)}if grid[i][m-1] == 1 {bfs(grid, i, m-1)}}// 處理上下邊界的陸地for j := 0; j < m; j++ {if grid[0][j] == 1 {bfs(grid, 0, j)}if grid[n-1][j] == 1 {bfs(grid, n-1, j)}}// 統計剩余的陸地(孤島)數量for i := 0; i < n; i++ {for j := 0; j < m; j++ {if grid[i][j] != 0 {grid[i][j]--}}}for i := 0;i < n;i++{for j := 0;j < m-1;j++{fmt.Printf("%d ",grid[i][j])}fmt.Println(grid[i][m-1])}
}

6.水流問題

從第一組邊界逆流而上,第二組邊界也逆流而上,然后同時標記過的點就是答案

package mainimport "fmt"var n, m int
var dir = [][]int{{-1, 0}, // 上{0, -1}, // 左{1, 0},  // 下{0, 1},  // 右
}// dfs 函數:從(x,y)開始遍歷,只向不低于當前高度的方向移動
func dfs(grid [][]int, visited [][]bool, x, y int) {if visited[x][y] {return}visited[x][y] = truefor i := 0; i < 4; i++ {nextx := x + dir[i][0]nexty := y + dir[i][1]// 邊界檢查if nextx < 0 || nextx >= n || nexty < 0 || nexty >= m {continue}// 只向不低于當前高度的方向遍歷(從低向高)if grid[x][y] > grid[nextx][nexty] {continue}dfs(grid, visited, nextx, nexty)}
}func main() {fmt.Scan(&n, &m)// 初始化網格grid := make([][]int, n)for i := range grid {grid[i] = make([]int, m)}// 讀取網格數據for i := 0; i < n; i++ {for j := 0; j < m; j++ {fmt.Scan(&grid[i][j])}}// 初始化兩個邊界訪問標記數組firstBorder := make([][]bool, n)secondBorder := make([][]bool, n)for i := range firstBorder {firstBorder[i] = make([]bool, m)secondBorder[i] = make([]bool, m)}// 從最左列和最右列開始遍歷for i := 0; i < n; i++ {dfs(grid, firstBorder, i, 0)          // 第一組邊界:最左列dfs(grid, secondBorder, i, m-1)       // 第二組邊界:最右列}// 從最上行和最下行開始遍歷for j := 0; j < m; j++ {dfs(grid, firstBorder, 0, j)          // 第一組邊界:最上行dfs(grid, secondBorder, n-1, j)       // 第二組邊界:最下行}// 輸出同時被兩組邊界遍歷到的節點坐標for i := 0; i < n; i++ {for j := 0; j < m; j++ {if firstBorder[i][j] && secondBorder[i][j] {fmt.Printf("%d %d\n", i, j)}}}
}

7.建造最大孤島

package mainimport "fmt"var n, m int
var dir = [][]int{{-1, 0}, // 上{0, -1}, // 左{1, 0},  // 下{0, 1},  // 右
}// dfs 函數:從(x,y)開始遍歷,只向不低于當前高度的方向移動
func dfs(grid [][]int, visited [][]bool, x, y int) {if visited[x][y] {return}visited[x][y] = truefor i := 0; i < 4; i++ {nextx := x + dir[i][0]nexty := y + dir[i][1]// 邊界檢查if nextx < 0 || nextx >= n || nexty < 0 || nexty >= m {continue}// 只向不低于當前高度的方向遍歷(從低向高)if grid[x][y] > grid[nextx][nexty] {continue}dfs(grid, visited, nextx, nexty)}
}func main() {fmt.Scan(&n, &m)// 初始化網格grid := make([][]int, n)for i := range grid {grid[i] = make([]int, m)}// 讀取網格數據for i := 0; i < n; i++ {for j := 0; j < m; j++ {fmt.Scan(&grid[i][j])}}// 初始化兩個邊界訪問標記數組firstBorder := make([][]bool, n)secondBorder := make([][]bool, n)for i := range firstBorder {firstBorder[i] = make([]bool, m)secondBorder[i] = make([]bool, m)}// 從最左列和最右列開始遍歷for i := 0; i < n; i++ {dfs(grid, firstBorder, i, 0)          // 第一組邊界:最左列dfs(grid, secondBorder, i, m-1)       // 第二組邊界:最右列}// 從最上行和最下行開始遍歷for j := 0; j < m; j++ {dfs(grid, firstBorder, 0, j)          // 第一組邊界:最上行dfs(grid, secondBorder, n-1, j)       // 第二組邊界:最下行}// 輸出同時被兩組邊界遍歷到的節點坐標for i := 0; i < n; i++ {for j := 0; j < m; j++ {if firstBorder[i][j] && secondBorder[i][j] {fmt.Printf("%d %d\n", i, j)}}}
}

8.島嶼周長

package mainimport ("bufio""fmt""os""strconv""strings"
)func main() {scanner := bufio.NewScanner(os.Stdin)scanner.Scan()line := scanner.Text()n, m := parseInput(line)// 初始化 gridgrid := make([][]int, n)for i := range grid {grid[i] = make([]int, m)}// 讀入 grid 數據for i := 0; i < n; i++ {scanner.Scan()line := scanner.Text()values := parseLine(line, m)for j := 0; j < m; j++ {grid[i][j] = values[j]}}sum := 0   // 陸地數量cover := 0 // 相鄰數量for i := 0; i < n; i++ {for j := 0; j < m; j++ {if grid[i][j] == 1 {sum++ // 統計總的陸地數量// 統計上邊相鄰陸地if i-1 >= 0 && grid[i-1][j] == 1 {cover++}// 統計左邊相鄰陸地if j-1 >= 0 && grid[i][j-1] == 1 {cover++}// 為什么沒統計下邊和右邊? 因為避免重復計算}}}fmt.Println(sum*4 - cover*2)
}// parseInput 解析 n 和 m
func parseInput(line string) (int, int) {parts := strings.Split(line, " ")n, _ := strconv.Atoi(parts[0])m, _ := strconv.Atoi(parts[1])return n, m
}// parseLine 解析一行中的多個值
func parseLine(line string, count int) []int {parts := strings.Split(line, " ")values := make([]int, count)for i := 0; i < count; i++ {values[i], _ = strconv.Atoi(parts[i])}return values
}

9.字符串接龍

1、圖中的線是如何連在一起的

在搜索的過程中,我們可以枚舉,用26個字母替換當前字符串的每一個字符,在看替換后 是否在 strList里出現過,就可以判斷兩個字符串是否是鏈接的。

2、起點和終點的最短路徑長度

首先題目中并沒有給出點與點之間的連線,而是要我們自己去連,條件是字符只能差一個。所以判斷點與點之間的關系,需要判斷是不是差一個字符,如果差一個字符,那就是有鏈接。然后就是求起點和終點的最短路徑長度,在無權圖中,求最短路,用深搜或者廣搜就行,沒必要用最短路算法。在無權圖中,用廣搜求最短路最為合適,廣搜只要搜到了終點,那么一定是最短的路徑。因為廣搜就是以起點中心向四周擴散的搜索。

另外需要有一個注意點:

  • 本題是一個無向圖,需要用標記位,標記著節點是否走過,否則就會死循環!
  • 使用哈希表來檢查字符串是否出現在字符串集合里更快一些

這道題好難啊!!!(需要二刷)

package main
import("fmt"
)
var count int
func bfs(start,end string,strset map[string]bool)int{visited := make(map[string]int)que := []string{start}visited[start] = 1for len(que) > 0{word := que[0]que = que[1:]path := visited[word]for i := 0;i < len(word);i++{newWord := []byte(word)for j := 0;j < 26;j++{newWord[i] = byte('a'+j)newString := string(newWord)if newString == end{return path + 1}if strset[newString] && visited[newString]==0{//當前單詞沒有遍歷過且新單詞在給定的集合當中visited[newString] = path + 1que = append(que,newString)}}}}return 0//沒找到
}func main(){var num intfmt.Scan(&num)var start,end,str stringfmt.Scan(&start,&end)strset := make(map[string]bool,num)for i := 0;i < num;i++{fmt.Scan(&str)strset[str] = true}result := bfs(start,end,strset)fmt.Println(result)
}

10.有向圖的完全可達性

如果是無權的。鄰接矩陣就是:如果a和b相連接,a和c連接,那么graph[a][b] = 1.graph[a][c] = 1。如果是鄰接表,那么graph[a] = [b,c]

思路:構建鄰接表,如果遇到了沒有經歷過的節點visited置為true。隨后遍歷他的鄰接表。如果遇到新的節點,就接著遞歸遍歷,并且置為true。直到最后。

package mainimport ("fmt"
)func dfs(graph [][]int, key int, visited []bool) {visited[key] = truefor _,neighbor := range graph[key]{if visited[neighbor] == false{dfs(graph,neighbor,visited)}}
}func main(){var n, k intfmt.Scan(&n, &k)//n個節點,k個邊graph := make([][]int,n+1)for i := 0;i < k;i++{var u,v intfmt.Scan(&u,&v)graph[u] = append(graph[u],v) }visited := make([]bool,n+1)dfs(graph,1,visited)for i := 1; i <= n; i++ {if !visited[i] {fmt.Println(-1)return}}fmt.Println(1)
}

11.單詞接龍

感悟:這道題的本質和字符串接龍是一模一樣的。。下午刷完,晚上看這道題就暈了。類似于層序遍歷。

func ladderLength(beginWord string, endWord string, wordList []string) int {wordSet := make(map[string]bool,len(wordList))for _,word := range wordList{wordSet[word] = true}if !wordSet[endWord]{return 0}visited := make(map[string]int)visited[beginWord] = 1que := []string{beginWord}for len(que) > 0{cur := que[0]que = que[1:]//出隊列path := visited[cur]for i := 0;i < len(cur);i++{newstr := []byte(cur)for j := 0;j < 26;j++{newstr[i] = byte('a'+j)nextword := string(newstr)if nextword == endWord{return path + 1//找到了}if visited[nextword] == 0 && wordSet[nextword]{//能找到,但是沒有遍歷過visited[nextword] = path + 1que = append(que,nextword)}}}}    return 0
}

12.鑰匙和房間

感悟:這道題的本質就是圖的連通性的問題。每個房間對應個節點,房間里的鑰匙對應節點間的“邊”。所以即轉換成起始節點遍歷所有節點。選擇DFS,是因為很契合DFS的邏輯“深度優先,遞歸探索。”

func canVisitAllRooms(rooms [][]int) bool {visited := make([]bool,len(rooms))var dfs func(key int)dfs = func(key int){if visited[key]{return}visited[key] = truefor _,i := range rooms[key]{dfs(i)}}dfs(0)for i := range visited{if visited[i] == false{return false}}return true
}

B.并查集

并查集主要有兩個功能:

  • 將兩個元素添加到一個集合中。
  • 判斷兩個元素在不在同一個集合

并查集模板

package mainimport ("fmt"
)const MaxNodes = 101var n int
var father [MaxNodes]int// 初始化并查集
func initialize() {for i := 1; i <= n; i++ {father[i] = i}
}// 并查集里尋根的過程
func find(u int) int {if u == father[u] {return u}father[u] = find(father[u])return father[u]
}// 判斷 u 和 v 是否找到同一個根
func isSame(u, v int) bool {return find(u) == find(v)
}// 將 v->u 這條邊加入并查集
func join(u, v int) {rootU := find(u)rootV := find(v)if rootU != rootV {father[rootV] = rootU}
}func main() {var m, s, t, source, destination intfmt.Scan(&n, &m)initialize()for i := 0; i < m; i++ {fmt.Scan(&s, &t)join(s, t)}fmt.Scan(&source, &destination)if isSame(source, destination) {fmt.Println(1)} else {fmt.Println(0)}
}

1.冗余連接

方法一深搜:每遍歷一條邊的時候,比如[u,v],首先判斷u是否能與v連通。如果不能,將其放入連通表中。如果可以連通,那就把那條邊返回。對于深搜的思路:比如判斷2和3能不能連通。遍歷2的連通表,比如數字是1.然后接著就去判斷1和3的連通性了。如果在1的連通表的可以找到3,那么就說明2,3連通。然后遞歸返回。

func findRedundantConnection(edges [][]int) []int {graph := make(map[int][]int)visited := make(map[int]bool)var dfs func(u, v int) booldfs = func(u, v int) bool {if u == v {return true}visited[u] = truefor _, next := range graph[u] {if !visited[next] {// 關鍵修復:如果遞歸找到路徑,立即返回trueif dfs(next, v) {return true}}}return false}for _, edge := range edges {u, v := edge[0], edge[1]// 重置訪問標記for node := range visited {visited[node] = false}if dfs(u, v) {return []int{u, v}}// 將當前邊加入圖中graph[u] = append(graph[u], v)graph[v] = append(graph[v], u)}return []int{}
}

方法二:并查集:

首先記住并查集的初始化方式,還有find函數的思想。然后就一次遍歷邊集的,然后查看x和y是否有同一個根節點。如果有了,就證明再加那條邊就冗余了。

func findRedundantConnection(edges [][]int) []int {parent := make([]int,len(edges) + 1)// 初始化并查集,每個節點的父節點指向自己for i := 1;i <= len(edges);i++{parent[i] = i}// 查找根節點(帶路徑壓縮)var find func(int) intfind = func(x int) int {if parent[x] != x {parent[x] = find(parent[x]) // 路徑壓縮}return parent[x]
//處理當前邏輯:對于parent[x]通過若干的遞歸和回溯,已經找到了目前他所對應的根節點了。所以直接返回}for _,edge := range edges{u,v := edge[0],edge[1]rootU := find(u)rootV := find(v)if rootU == rootV{return edge}parent[rootV] = rootU}return nil
}

處理當前層邏輯:在遞歸調用返回后,利用返回的結果來完成當前層需要完成的任務

拓撲排序的過程

  1. 找到入度為0 的節點,加入結果集
  2. 將該節點從圖中移除

循環以上兩步,直到 所有節點都在圖中被移除了。結果集的順序,就是我們想要的拓撲排序順序?

拓撲排序判斷有沒有環:0加入到結果集之后,找不到入度為0的點

C.最小生成樹理論

prim && kruskal

感覺面試不怎么考。。。

D.拓撲排序

拓撲排序指的是一種 解決問題的大體思路, 而具體算法,可能是廣搜也可能是深搜。

1.課程表

func canFinish(numCourses int, prerequisites [][]int) bool {inDegree := make([]int,numCourses)//入度graph := make([][]int,numCourses)//鄰接表for _,pre := range prerequisites{//初始化course,precourse := pre[0],pre[1]graph[precourse] = append(graph[precourse],course)inDegree[course]++}queue := []int{}for i := 0;i < numCourses;i++{//入度為0點點加入隊列if inDegree[i] == 0{queue = append(queue,i)}}count := 0for len(queue) > 0{cur := queue[0]queue = queue[1:]count++// 遍歷當前課程的所有后續課程for _,nextCourse := range graph[cur]{inDegree[nextCourse]--if inDegree[nextCourse] == 0{queue = append(queue,nextCourse)}}}return count == numCourses
}

2.課程表2??

方法一:開兩個數組(冗余)方法二:

func findOrder(numCourses int, prerequisites [][]int) []int {inDegree := make([]int, numCourses)graph := make(map[int][]int)for _, val := range prerequisites {course, precourse := val[0], val[1]inDegree[course]++graph[precourse] = append(graph[precourse], course)}res := []int{}// 第一輪:添加所有入度為0的課程for i := 0; i < numCourses; i++ {if inDegree[i] == 0 {res = append(res, i)}}// 使用res作為隊列,i作為指針for i := 0; i < len(res); i++ {cur := res[i]for _, next := range graph[cur] {inDegree[next]--if inDegree[next] == 0 {res = append(res, next)}}}if len(res) != numCourses {return []int{}}return res
}

感悟:這也太優雅了吧。len(res)?在循環過程中會不斷增長。res同時充當結果容器去存儲結果,同時i也相當于指針去標記當前處理的位置

E.最短路算法理論

感覺面試不怎么考。。。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/923682.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/923682.shtml
英文地址,請注明出處:http://en.pswp.cn/news/923682.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于Echarts+HTML5可視化數據大屏展示-白茶大數據溯源平臺V2

效果展示&#xff1a;代碼結構&#xff1a;主要代碼實現 index.html布局 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta n…

Linux 系統網絡配置及 IP 地址相關知識匯總

Linux 系統網絡配置及 IP 地址相關知識匯總 一、IP地址基礎 IP地址&#xff1a;在計算機網絡中用來唯一標識一臺設備的一組數字。 二、IPv4相關知識 1. IPv4的表示方法 采用點分十進制表示&#xff0c;即由4個0-255的十進制數通過點分隔組成&#xff08;如192.168.1.1&#xff…

百度股價突破120美元創年內新高,AI云成為增長新引擎

美東時間9月16日&#xff0c;百度&#xff08;NASDAQ: BIDU&#xff09;美股大漲近8%&#xff0c;收盤價突破120美元&#xff0c;站上124美元高位&#xff0c;創2023年10月以來新高。北京時間9月17日港股開盤&#xff0c;百度&#xff08;09888.HK&#xff09;港股再次暴漲&…

《彩虹六號:圍攻》“Siege X”發布會3月14日舉行!

使用jQuery的常用方法與返回值分析 jQuery是一個輕量級的JavaScript庫&#xff0c;旨在簡化HTML文檔遍歷和操作、事件處理以及動畫效果的創建。本文將介紹一些常用的jQuery方法及其返回值&#xff0c;幫助開發者更好地理解和運用這一強大的庫。 1. 選擇器方法 jQuery提供了多種…

[從青銅到王者] Spring Boot+Redis+Kafka電商場景面試全解析

互聯網大廠Java開發崗技術面試實錄&#xff1a;嚴肅面試官VS搞笑程序員謝飛機 文章內容 第一輪&#xff1a;基礎框架與并發控制&#xff08;電商系統基礎能力&#xff09; 面試官&#xff08;嚴肅&#xff09;&#xff1a;歡迎進入面試環節&#xff0c;首先請用3句話總結Spring…

【DMA】DMA架構解析

目錄 1 DMA架構 1. 芯片架構圖一覽 2. AHB總線矩陣掛載 3. AHB1/APB1的橋和AHB1/APB2的橋 4. DMA1 和 DMA2 的區別 2 AHB總線矩陣 1 DMA架構 1. 芯片架構圖一覽 2. AHB總線矩陣掛載 stm32F411 芯片的 AHB 總線矩陣上共掛載了 6 主 5 從 六主&#xff1a; Icode-bus、D…

GPS 定位器:精準追蹤的“隱形守護者”

GPS 定位器&#xff1a;精準追蹤的“隱形守護者” 一、什么是 GPS 定位器&#xff1f; GPS 定位器是一種基于 全球定位系統&#xff08;Global Positioning System, GPS&#xff09; 的智能追蹤設備。 通過接收衛星信號并結合通信模塊&#xff08;如 4G、NB-IoT&#xff09;&am…

前端拖拽排序實現

1. 使用 HTML5 事件 觸發時機 核心任務 dragstart 開始拖拽時 準備數據&#xff0c;貼上標簽 dragover 經過目標上方時 必須 preventDefault()&#xff0c;發出“允許放置”的信號 dragleave 離開目標上方時 清理高亮等臨時視覺效果 drop 在目標上松手時 接收數據…

arm coresight

這是一個arm設計的調試基礎架構&#xff0c;我們常用的debug基本都包含在內。比如ETM、PTM、ITM、HTM、ETB等。 注意ETM、PTM、ITM、HTM、ETB是coresight的子集。這些工具相比普通debug的斷點調試&#xff0c;需要更高的專業水平&#xff0c;因此也用于復雜軟件故障定位、性能…

《華為基本法》 —— 企業發展的導航儀

當一家企業從 “小作坊” 向 “規模化組織” 跨越時&#xff0c;最需要的是什么&#xff1f;華為的答案&#xff0c;藏在 1998 年出臺的《華為基本法》里。1998 年&#xff0c;《華為基本法》正式頒布&#xff0c;這部凝結華為早期經營智慧的綱領性文件&#xff0c;不僅為華為從…

【完整源碼+數據集+部署教程】傳統韓文化元素分割系統: yolov8-seg-GFPN

背景意義 研究背景與意義 隨著全球化的加速&#xff0c;傳統文化的保護與傳承面臨著前所未有的挑戰。尤其是韓國的傳統文化&#xff0c;作為東亞文化的重要組成部分&#xff0c;蘊含著豐富的歷史、藝術和哲學內涵。然而&#xff0c;隨著現代化進程的推進&#xff0c;許多傳統文…

構建AI智能體:三十五、決策樹的核心機制(一):刨根問底鳶尾花分類中的參數推理計算

一、初識決策樹想象一個生活中的場景&#xff0c;我們去水果店買一個西瓜&#xff0c;該怎么判斷一個西瓜是不是又甜又好的呢&#xff1f;我們可能會問自己一系列問題&#xff1a;首先看看它的紋路清晰嗎&#xff1f;如果“是”&#xff0c;那么它可能是個好瓜。如果“否“&…

c語言中實現線程同步的操作

線程 常見問題 同步權限 在多線程 / 多進程并發時&#xff0c;為避免共享資源&#xff08;如內存變量、硬件設備、文件&#xff09;被同時修改導致的數據不一致&#xff0c;需要通過 “同步機制” 控制誰能訪問資源 ——“獲取同步權限” 就是線程 / 進程申請這種訪問資格的過程…

一臺設備管理多個 GitHub 賬號:從配置到切換的完整指南

一臺設備管理多個 GitHub 賬號&#xff1a;從配置到切換的完整指南 在日常開發中&#xff0c;我們經常需要在同一臺電腦上使用多個 GitHub 賬號&#xff08;比如個人賬號和工作賬號&#xff09;。但默認情況下&#xff0c;Git 會優先使用全局配置的賬號&#xff0c;導致推送代…

即插即用,秒入虛擬:TouchDIVER Pro 觸覺手套 賦能 AR/VR 高效交互

一、即插即用&#xff0c;零門檻開啟沉浸之旅 在XR&#xff08;擴展現實&#xff09;技術高速發展的今天&#xff0c;用戶對“真實感”的追求愈發迫切。Weart公司旗下旗艦產品TouchDIVER Pro觸覺手套&#xff0c;憑借無需適配器、無需復雜設置的極簡設計&#xff0c;打破傳統觸…

GitHub熱榜項目 - 日榜之應用場景與未來發展趨勢

一、引言GitHub熱榜項目 - 日榜呈現出豐富多樣的技術成果&#xff0c;這些項目蘊含著巨大的應用潛力&#xff0c;并且對未來數智化技術的發展有著重要的指示作用。深入探究其應用場景以及未來發展趨勢&#xff0c;能讓我們更好地把握技術發展方向&#xff0c;將這些前沿技術應用…

Linux網絡:socket編程TCP

文章目錄前言一&#xff0c;服務器端流程1-1 綁定協議1-2 綁定IP和端口1-3 監聽客戶端1-4 接收連接1-5 收發數據1-6 關閉連接1-7 服務端整體代碼二&#xff0c;客戶端流程2-1 指定地址和端口2-2 連接服務器2-3 發送消息2-4 客戶端整體代碼前言 TCP 的通信過程就像兩個人打電話…

飛書智能查詢機器人搭建說明文檔

飛書智能查詢機器人搭建說明文檔 一、使用手冊 1. 創建飛書機器人應用 如果僅需對接已有機器人應用則可跳過該步驟&#xff08;建議各業務部門獨立使用各自的機器人應用&#xff09;。在飛書開發者后臺中創建企業自建應用&#xff0c;添加機器人應用能力并申請對應的身份權限…

藍色系列包裝行業網站 適合企業站,帶手機版自適應

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 藍色通用企業網站是基于SDCMS四合一企業網站管理系統開發的模板&#xff0c;適合企業站&#xff0c;帶手機版。 四網合一企業網站管理系統是一個以PHPMySQL/Sqlite進行開發的四網合一網…

【大模型:知識圖譜】--6.Neo4j DeskTop安裝+使用

上一期講了圖知識庫的安裝&#xff0c; 【圖數據庫】--Neo4j 安裝_neo4j安裝-CSDN博客 現在來看看可視化管理程序&#xff1a;Neo4j DeskTop的安裝. 需要先安裝java環境&#xff0c;具體看上面 目錄 1.Neo4j DeskTop版下載 2.Neo4j DeskTop版安裝 3.Neo4j DeskTop版使用 …