算法—leetcode—51

601 阅读2分钟

题目

(51.)N 皇后

题目描述

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

提示

皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

示例

示例一

输入:4
输出:[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。

思路

框架

1、路径:也就是已经做出的选择;
2、选择列表:当前可以做的选择;
3、结束条件:到达决策树底层,无法再做选择的条件。

N皇后问题对应框架的解释

路径:board中小于row的那些行都已经成功放置了皇后
选择列表:第row行的所有列都是放置皇后的选择
结束条件:row超过board的最后一行

准备条件

1、初始化一个棋盘的二为数组
2、定义一个校验是否有效位置的函数isValid
3、按框架思路书写循环代码

框架

for 选择 in 选择列表:
    # 做选择
    将该选择从选择列表移除
    路径.add(选择)
    backtrack(路径, 选择列表)
    # 撤销选择
    路径.remove(选择)
    将该选择再加入选择列表

代码

package leetcode

import (
    "log"
    "encoding/json"
)

// 定义全局结果数组
var result [][]string

// solveNQueens
// N皇后
// 输入棋盘边长 n,返回所有合法的放置
func solveNQueens(n int) [][]string {
	// 初始化result
	result = [][]string{}
	board := make([][]string, n, n)

	// 初始化路径track ".",选择后改为"Q"
	for i := 0; i < n; i++ {
		tmp := make([]string, n, n)
		for j := 0; j < n; j++ {
            tmp[j] = "."
		}
        board[i] = tmp
	}
    temp, _ := json.Marshal(board)
    log.Println(string(temp))
	// 递归选择,从第一行选择到第N行回溯
	backtrack(board, 0)

	// 返回结果
	return result
}

// backtrack
// 路径:board中小于row的那些行都已经成功放置了皇后
// 选择列表:第row行的所有列都是放置皇后的选择
// 结束条件:row超过board的最后一行
func backtrack(board [][]string, row int) {
	// 结束条件,row循环到棋盘底部时结束本次选择
	if len(board) == r8ikkkkkkkkkkow {
        tmp := make([]string, 0)
		// 将每行的选择结果改为字符串  [[".",".","Q","."],..] => ["..Q.", ...]
		for _, v := range board {
			str := ""
			for _, e := range v {
				str += e
			}
			tmp = append(tmp, str)
		}
		// 将结果push到选择结果集中
        // 存储多种解决方案
		result = append(result, tmp)
		return
	}
    
    // 获取指定行的长度
	n := len(board[row])
	// 选择列表为1-N列
	for col := 0; col < n; col++ {
		// 判断此处是否可以选择皇后(同行,同列,对角不能存在多个皇后)
		if !isValid(board, row, col) {
			continue
		}
		// 选择皇后
		board[row][col] = "Q"
		// 进行下一行决策选择
		backtrack(board, row+1)
		// 撤回选择
		board[row][col] = "."
	}
}

// isValid
// 验证指定位置是否可以放置皇后
// @param board 当前棋盘
// @param row 当前行
// @param col 当前列
func isValid(board [][]string, row, col int) bool {
	n := len(board)
	// 检查列是否有皇后互相冲突
	for i := 0; i < n; i++ {
		if board[i][col] == "Q" {
            log.Println("列冲突", row, col)
			return false
		}
	}
	// 检查右上方是否有皇后互相冲突
	for i, j := row-1, col+1; i >= 0 && j < n; i, j = i-1, j+1 {
		if board[i][j] == "Q" {
            log.Println("右上方", row, col)
			return false
		}
	}
	// 检查左上方是否有皇后互相冲突
	for i, j := row-1, col-1; i >= 0 && j >= 0; i, j = i-1, j-1 {
		if board[i][j] == "Q" {
            log.Println("左上方", row, col)
			return false
		}
	}
	return true
}

参考

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/n-…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

labuladong的算法小抄