51. N-Queens
经典的题目……很有趣
ref:http://blog.csdn.net/hackbuteer1/article/details/6657109
首先说一下判断一个格子是不是能放,行列+两侧斜角比较非常笨重,可以用一个一维数组来表示int[] queuePos = new int[n]. 每一个格子表示这行上皇后的位置。
1. 首先一个行只有一个皇后的位置,所以行自然没有重复的皇后
2. 对于列,我们寻找到现在这一行之前的所有行,有没有皇后已经被放在同样的列上,如果没有就可以放
3. 对于斜角,处在斜角上的格子有一个性质Math.abs(row - rowWeWannaPlace) == Math.abs(queuePos[row] - colWeWannaPlace). 所以也是检查一遍就行了
helper函数接受两个参数,一个queuePos的一维数组,一个当前行
1 如果当前行 == n 2 3 添加结果 4 5 不然对于每一列 6 7 如果这个位置能放 8 9 放皇后在这个位置上 10 11 递归helper(row + 1)
所以整体的代码是:
1 public List<List<String>> solveNQueens(int n) { 2 List<List<String>> res = new ArrayList<>(); 3 int[] queuePos = new int[n]; 4 Arrays.fill(queuePos, -1); 5 queue(res, queuePos, 0); 6 return res; 7 } 8 9 private boolean canPlace(int[] queuePos, int row, int col) { 10 for(int i = 0; i < row; i++) { 11 if(queuePos[i] == col) { 12 return false; 13 } 14 if(Math.abs(i - row) == Math.abs(queuePos[i] - col)) { 15 return false; 16 } 17 } 18 return true; 19 } 20 21 private void queue(List<List<String>> res, int[] queuePos, int row) { 22 int n = queuePos.length; 23 if(row == n) { 24 List<String> cur = generateResStr(queuePos); 25 res.add(cur); 26 return; 27 } 28 for(int i = 0; i < n; i++) { 29 if(canPlace(queuePos, row, i)) { 30 queuePos[row] = i; 31 queue(res, queuePos, row + 1); 32 } 33 } 34 } 35 36 private List<String> generateResStr(int[] queuePos) { 37 int n = queuePos.length; 38 char[] row = new char[n]; 39 Arrays.fill(row, '.'); 40 List<String> res = new ArrayList<>(); 41 for(int i = 0; i < queuePos.length; i++) { 42 row[queuePos[i]] = 'Q'; 43 res.add(new String(row)); 44 Arrays.fill(row, '.'); 45 } 46 return res; 47 }
相当于遍历一棵树,树的层数是N,每层的节点数数是可以放的列,所以总复杂度是O(n!)