【代碼隨想錄】算法訓練計劃30
1、51. N 皇后
按照國際象棋的規則,皇后可以攻擊與之處在同一行或同一列或同一斜線上的棋子。
n 皇后問題 研究的是如何將 n 個皇后放置在 n×n 的棋盤上,并且使皇后彼此之間不能相互攻擊。
給你一個整數 n ,返回所有不同的 n 皇后問題 的解決方案。
每一種解法包含一個不同的 n 皇后問題 的棋子放置方案,該方案中 ‘Q’ 和 ‘.’ 分別代表了皇后和空位。
我寫的:
我先想了一個思路,然后去看代碼回想錄,和我想的一樣,我取巧了,直接看了她的寫的,不過都理解
但也有一點別的收獲
他把res設為了全局變量,這樣就連&和*都不需要了
收獲:
全局的聲明:var res [][]string
函數內初始化:res = [][]string{}
這樣就不需要取值操作了——就是&,* 這些個
func solveNQueens(n int) [][]string {res := make([][]string, 0)board := make([][]string, n)//下邊就是把數組空的位置都初始化為".",代表空for i := 0; i < n; i++ {board[i] = make([]string, n)}for i := 0; i < n; i++{for j := 0; j < n; j++ {board[i][j] = "."}}backtrack(board, 0, &res)return res
}
func backtrack(board [][]string, row int, res *[][]string) {size := len(board)//結束條件是到board,就是到最后一行也添加皇后了if row == size {ans := make([]string, size)for i := 0; i < size; i++ {ans[i] = strings.Join(board[i], "")}*res = append(*res, ans)return}for col := 0; col < size; col++ {if !isValid(board, row, col){continue}board[row][col] = "Q"backtrack(board, row+1, res)board[row][col] = "."}
}
func isValid(board [][]string, row,col int) (res bool){n := len(board)//判斷這一列上下行是否有Qfor i := 0; i < row; i++ {if board[i][col] == "Q" {return false}}//判斷這一行左右列是否有Qfor i := 0; i < col; i++ {if board[row][i] == "Q" {return false}}//為什么不判斷左下線和右下線的原因很簡單,因為下邊的行還沒有給皇后,所以不需要判斷//判斷左上線是否有Qfor i, j := row, col; i >= 0 && j >= 0; i, j = i-1, j-1 {if board[i][j] == "Q" {return false}}//判斷右上線是否有Qfor i, j := row, col; i >= 0 && j < n; i,j = i-1,j+1 {if board[i][j] == "Q" {return false}}return true
}
2、37. 解數獨
編寫一個程序,通過填充空格來解決數獨問題。
數獨的解法需 遵循如下規則:
數字 1-9 在每一行只能出現一次。
數字 1-9 在每一列只能出現一次。
數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。(請參考示例圖)
數獨部分空格內已填入了數字,空白格用 ‘.’ 表示。
提示:
board.length == 9
board[i].length == 9
board[i][j] 是一位數字或者 ‘.’
題目數據 保證 輸入數獨僅有一個解
我第一次只能寫到如下這么多了
//做一個二維的字典或者數組,方便第三個判斷,0-02,1-35,2-68或者0-13,1-46,2-79,
jgg := [3][2]{{0,2},{3,5},{6,8},
}
func solveSudoku(board [][]byte) {list := make([]int, 0)backtrack(list []int, &board)return board
}
func backtrack(board *[][]byte) {//到第九行結束,一行一行的填入,每一行要填入9個數字//記住,這個數獨只有唯一一個解if Index == 9 {ans := make([]int, len(list))copy(ans, list)*board}for i := 0; i <= 9; i++ {//我的難點就是不知道怎么去知道這個行,列,然后去嗯...給他整上數字}
}//判斷所填入數字是否滿足條件
func mz(board *[][]byte, shu,row,col int) bool{//左右這個數沒出現過,i不變,j變,情況下,可以添加這個數字for j := 0; j < 9 ; j++ {if board[row][j] == shu {return false}}//上下這個數沒出現過, i變,j不變for i := 0; i < 9; i++ {if board[i][col] == shu {return false}}//判斷他所在區域的9個格子是否出現-除以三-判斷是第幾個格子h := row/3l := col/3for i := jgg[h][0]; i <= jgg[h][1] {for j := jgg[l][0]; j <= jgg[l][1]{if board[i][j] == shu {return false}}}return true
}
看題解理解后如下啊:
思路:
- 第一步咱們很清楚的知道,需要判斷加入的數是否滿足條件,所以寫了mz函數,感覺我判斷格子的方法有點臃腫了
- 好,開始正題,進入backtrack
- 為什么這次沒有和solveSudoku分開單獨寫一個呢,在于這個題目人家不要返回值,而且填寫的是board,二維的,咱要是在分開的backtrack函數用*[][]int,其實,傳不進去單個值,所以直接在solveSudoku函數先聲明,再初始化,再使用
4.好了開始說說初始化,也就是backtrack的主體,首先是這個雙重for循環,記得水仙花數,打印圖形嗎,這類的題目就是用了雙重for循環來代表要添加的元素所在的行列 - 接著判斷不是’.'的不需要變成數字,跳過當前循環,進入下一層
- 重重點開始
- 首先是’1’-'9’是選擇列表,但是因為board是[][]byte類型,在你追加的時候需要類型轉換byte(shu),判斷是否滿足mz的傳參也需要
- 接著是循環,不過這里用了if,多了一層判斷,為真就return true
- 接著回溯,都知道
- 接著下邊又有兩個return,說實話,我還不太理解這三個return到底有什么妙用
- 關于方格的判斷條件啊,還是人家代碼隨想錄寫得好,值得看看,不過別擔心,不難理解
func solveSudoku(board [][]byte) {var backtrack func(board [][]byte) boolbacktrack = func(board [][]byte) bool {//雙重for循環,代表行列for i := 0; i < 9; i++ {for j := 0; j < 9; j++ {//只有當前位置為.的時候才可以添加數字,否則跳過這個數if board[i][j] != '.'{continue}//重點,填寫1-9是選擇列表,for shu := '1'; shu <= '9'; shu++ {if mz(board,byte(shu),i,j) == true {//追加board[i][j] = byte(shu)//循環if backtrack(board) == true {return true}//回溯board[i][j] = '.'}}return false}}return true}backtrack(board)
}
func backtrack(board *[][]byte) {}//判斷所填入數字是否滿足條件
func mz(board [][]byte, shu byte, row,col int) bool {//做一個二維的字典或者數組,方便第三個判斷,0-02,1-35,2-68或者0-13,1-46,2-79,jgg := [3][2]int{{0,2},{3,5},{6,8},}//左右這個數沒出現過,i不變,j變,情況下,可以添加這個數字for j := 0; j < 9 ; j++ {if board[row][j] == shu {return false}}//上下這個數沒出現過, i變,j不變for i := 0; i < 9; i++ {if board[i][col] == shu {return false}}//判斷他所在區域的9個格子是否出現-除以三-判斷是第幾個格子h := row/3l := col/3for i := jgg[h][0]; i <= jgg[h][1]; i++ {for j := jgg[l][0]; j <= jgg[l][1]; j++{if board[i][j] == shu {return false}}}return true
}