LeetCode 51 N-Queens 解题报告

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

Example:

Input: 4
Output: [
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.

题目意思比较简单,就是给定一个数字N,将N个皇后放在N*N的棋盘上,这N个皇后间相互不能攻击,国际象棋中皇是可以横竖斜着走,这里其实可以用简单的回溯法,由于已经有了一些限制条件,可知所有N个皇后不能在同一行上面,因为可简单按照一行一行来放置皇后。过程如下:

1. 将当前行号设置为0,选择第0行皇后的下一个可选位置,如果无可选位置程序结束,否则进入2

2. 判断当前行放的皇后位置是否合法,如果合法进入3,如果不合法进入4

3. 判断当前行号是否已达到最大,如果最大输出最前解,并到1;否则到下一行,并放置下一行的皇后可选位置

4. 判断当前行是否有下一个可选位置,如果有就放置,并到2;否则回到上一行,并放置上一行的皇后可选位置,并进入2

当回到上一行时,需要记得将本行置为不放置皇后状态,GO实现代码如下:

const (
	QUEEN byte = 'Q'
	EMPTY byte = '.'
)

// 行号,将当前行号的下一个可选位置
type PosNumber struct {
	index   int
	numbers []int
}

// 判断当前在i, j位置是否可放置皇后
func isValidPos(nQueenSolver [][]byte, n int, i int, j int) bool {
	for xIndx := 0; xIndx < i; xIndx++ {
		if nQueenSolver[xIndx][j] == QUEEN {
			return false
		}
	}

	xIndx := i - 1
	yIndx := j - 1
	for {
		if xIndx < 0 || yIndx < 0 {
			break
		}

		if nQueenSolver[xIndx][yIndx] == QUEEN {
			return false
		}

		xIndx--
		yIndx--
	}

	xIndx = i - 1
	yIndx = j + 1
	for {
		if xIndx < 0 || yIndx >= n {
			break
		}

		if nQueenSolver[xIndx][yIndx] == QUEEN {
			return false
		}

		xIndx--
		yIndx++
	}

	return true
}

func solveNQueens(n int) [][]string {
	nQueenSolvers := [][]string{}

	nQueenSolver := make([][]byte, n)
	for i := 0; i < n; i++ {
		nQueenSolver[i] = make([]byte, n)
	}

	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			for k := 0; k < n; k++ {
				nQueenSolver[j][k] = EMPTY
			}
		}

		nQueenSolver[0][i] = QUEEN

        // 存储每一行皇后的可选位置
		posStack := []PosNumber{}
		posStack = append(posStack, PosNumber{0, []int{}})

		curXPos := 0
		curYpos := i
		stepBack := false
		for {
			if len(posStack) == 0 {
				break
			}

            // 回溯
			if stepBack {
				if len(posStack[len(posStack)-1].numbers) != 0 {
					curXPos = posStack[len(posStack)-1].index
					curYpos = posStack[len(posStack)-1].numbers[0]

					posStack[len(posStack)-1].numbers = posStack[len(posStack)-1].numbers[1:]
				} else {
					for len(posStack) > 0 && len(posStack[len(posStack)-1].numbers) == 0 {
						for j := 0; j < n; j++ {
							nQueenSolver[posStack[len(posStack)-1].index][j] = EMPTY
						}

						posStack = posStack[0 : len(posStack)-1]
					}

					if len(posStack) == 0 {
						break
					}

					curXPos = posStack[len(posStack)-1].index
					for j := 0; j < n; j++ {
						nQueenSolver[curXPos][j] = EMPTY
					}

					curYpos = posStack[len(posStack)-1].numbers[0]

					posStack[len(posStack)-1].numbers = posStack[len(posStack)-1].numbers[1:]
				}

				stepBack = false
			}

			if isValidPos(nQueenSolver, n, curXPos, curYpos) {
				nQueenSolver[curXPos][curYpos] = QUEEN

				if curXPos == n-1 {
					nStr := make([]string, n)
					for j := 0; j < n; j++ {
						nStr[j] = string(nQueenSolver[j])
					}
					nQueenSolvers = append(nQueenSolvers, nStr)

					nQueenSolver[curXPos][curYpos] = EMPTY
					stepBack = true
					continue
				}

				curXPos++
				curYpos = 0
				numbers := []int{}
				for j := 1; j < n; j++ {
					numbers = append(numbers, j)
				}
				posStack = append(posStack, PosNumber{curXPos, numbers})
			} else {
				stepBack = true
			}
		}
	}

	return nQueenSolvers
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值