字串接龍
var queue *list.List
var visitMap map[string]bool
func main() {
var count int
fmt.Scanf("%d", &count)
var startStr, endStr string
fmt.Scanf("%s %s", &startStr, &endStr)
var strList = make([]string, count)
for i := 0; i < count; i++ {
var str string
fmt.Scanf("%s", &str)
strList[i] = str
}
fmt.Println(startStr, endStr, strList)
queue = list.New()
queue.PushBack(startStr)
visitMap = make(map[string]bool, len(strList)) // 存放字元的使用狀態
for _, v := range strList {
visitMap[v] = false
}
bfs(endStr, strList)
}
func bfs(target string, strList []string) {
// 本題的思路是構建無向圖,然後廣搜得到最短路徑
// 但是具體怎麼實現?先構建再廣搜?並不是,是一邊廣搜一邊半構建
// 具體過程是,從startStr出發,對於每一個字元,嘗試使用26個字母替換,如果替換後的新字串出現在strlist中,那麼加入佇列,路徑+1,直到最終找到endStr
// todo: 廣搜如何記錄層數,也就是路徑深度,應該是每一層都標記一下入隊長度,如果該層完全出隊,層度+1,太長就不寫了
for queue.Len() > 0 {
node := queue.Remove(queue.Front()).(string)
nodeRune := []rune(node)
for idx, _ := range nodeRune {
for i := 0; i < 26; i++ {
newStr := nodeRune
newStr[idx] = rune(i + 'a')
// 如果直接變成target,返回
if string(newStr) == target {
count++
return
}
// 遇到字典元素, 並且沒有使用過
if v, ok := visitMap[string(newStr)]; ok && !v {
visitMap[string(newStr)] = true
queue.PushBack(string(newStr))
}
}
}
}
}
有向圖完全可達性
package main
import (
"container/list"
"fmt"
)
var queue *list.List
var visited []bool
func main() {
//var c, l int
//fmt.Scanf("%d %d", &c, &l)
//
//// 構建鄰接矩陣儲存圖
//var graph = make([][]int, c)
//for i, _ := range graph {
// graph[i] = make([]int, c)
//}
//for i := 0; i < l; i++ {
// var x, y int
// fmt.Scanf("%d %d", &x, &y)
// graph[x-1][y-1] = 1
//}
//for _, v := range graph {
// fmt.Println(v)
//}
c := 4
//l := 4
graph := [][]int{{0, 1, 1, 0}, {1, 0, 0, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}
// dfs
// 本題原理就是找到首個節點到所有節點是否路徑可達,所以dfs判斷兩個節點是否存在路徑(路徑可達)
for i := 1; i < c; i++ {
visited = make([]bool, c)
if dfs(0, i, graph) == false { // 任意一個節點不可達,就是false
fmt.Printf("dfs %d false\n", i)
break
}
}
// bfs
for i := 1; i < c; i++ {
visited = make([]bool, c)
visited[0] = true
queue = list.New()
queue.PushBack(0)
if bfs(graph, i) == false {
fmt.Printf("bfs %d false\n", i)
break
}
}
fmt.Println("true")
}
func dfs(start, stop int, graph [][]int) bool {
// 遞迴終止條件,空,或者找到了target
visited[start] = true // 標記節點已經遍歷過
if start == stop {
return true
}
for idx, v := range graph[start] {
if v == 1 && !visited[idx] {
res := dfs(idx, stop, graph)
if res { // 某次遞迴出現了目標,直接返回true
return true
}
}
}
// 回溯
visited[start] = false
return false
}
func bfs(graph [][]int, target int) bool {
for queue.Len() > 0 {
node := queue.Remove(queue.Front()).(int)
if node == target {
return true
}
for i, v := range graph[node] {
if v == 1 && !visited[i] {
visited[i] = true
queue.PushBack(i)
}
}
}
return false
}
463 島嶼周長
var dirPath = [4][2]int{{0,1}, {0,-1}, {1,0}, {-1,0}}
var sum int // 周長
var visited [][]bool
func islandPerimeter(grid [][]int) int {
// 很簡單的思路,計算所有的陸地,然後區分不同的周長
// 三面環水,周長為3,兩面,周長是2... 四周幾格水周長就是幾,邊界也算作水
sum = 0
visited = make([][]bool, len(grid))
for i, _ := range visited {
visited[i] = make([]bool, len(grid[0]))
}
for i:=0; i<len(grid); i++ {
for j:=0; j<len(grid[0]); j++ {
if grid[i][j] == 1 && !visited[i][j] {
dfs(i, j, grid)
}
}
}
return sum
}
func dfs(x, y int, graph [][]int) {
if graph[x][y] == 0 || visited[x][y] {
visited[x][y] = true
return
}
visited[x][y] = true
for _, dir := range dirPath {
next_x, next_y := x + dir[0], y+ dir[1]
if next_x < 0 || next_y<0 || next_x >= len(graph) || next_y >= len(graph[0]) {
sum += 1 // 當前陸地的周邊是邊界,視為水,周長+1
continue
}
if graph[next_x][next_y] == 0 { // 當前陸地的周邊是水,周長+1
sum += 1
}
if graph[next_x][next_y] == 1 && !visited[next_x][next_y] {
// 是新大陸
dfs(next_x, next_y, graph)
}
}
}