LeetCode51. N 皇后
N皇后问题也可以转化为树形问题,每一层代表格子的一行,每一个节点都有N种选择。
思路1:以52题的解法为基础,当递归到底时,根据record[]数组的状态信息,还原出皇后的位置。
判断斜线的方法(参考左神):如果(a,b)满足|a-i|==|b-j|,说明(a,b)和(i,j)处在同一条斜线上。
思路2:
判断斜线的方法(参考bobo):
设置两个大小为 2*n-1 的布尔数组,分别为 pie[2*n-1] 和 na[2*n - 1]。 表示n个格子一共有2*n - 1条斜线。
对角线pie,特点是每一条斜线经过格子的横纵坐标之和相等,因此,pie[i + j] 确定一条斜线。(n为4,pie对角线 i + j 的值分别为0,1,2,3,4,5,6)
对角线na,特点是每一条斜线经过格子的横纵坐标之差相等,因此,na[i-j+n-1] 确定一条斜线。(n为4,na对角线 i - j 的值分别为-3,-2,-1,0,1,2,3,为了方便从0开始,加上 4-1=3)
代码1(参考左神书,耗时 4ms):
class Solution { List<List<String>> res = new ArrayList<>(); public List<List<String>> solveNQueens(int n) { if (n < 1) return res; int[] record = new int[n]; // record[i]表示第i行皇后所在的列数 dfs(0, record, n); return res; } private void dfs(int row, int[] record, int n) { if (row == n) { res.add(generateBoard(n,record)); // 生成位置信息 return; } // 尝试将第row行的皇后摆放在第j列 for (int j = 0; j < n; j++) { if (isValid(record, row, j)) { record[row] = j; dfs(row + 1, record, n); } } } private boolean isValid(int[] record, int row, int j) { for (int k = 0; k < row; k++) { if (record[k] == j || Math.abs(row - k) == Math.abs(j - record[k])) { return false; } } return true; } // 根据record[]数组的状态信息,还原出皇后的位置。 // 在52题的基础上,添加此函数即可。 private List<String> generateBoard(int n, int[] record) { List<String> list = new ArrayList<>(); for (int i = 0; i < n; i++) { char[] temp = new char[n]; Arrays.fill(temp, '.'); temp[record[i]] = 'Q'; list.add(new String(temp)); } return list; } }
代码2(位运算):
M