是上一题的follow-up,问有总共几种方法。用全局变量易得,但是在java中不能像C++那么方便地用引用或指针传primitive参数。所以我觉得用return value来记录方法数更好!
package Level4;
import java.util.ArrayList;
/**
* N-Queens II
*
* Follow up for N-Queens problem.
*
* Now, instead outputting board configurations, return the total number of
* distinct solutions.
*
* http://www.leetcode.com/wp-content/uploads/2012/03/8-queens.png
*
*/
public class S52 {
public static void main(String[] args) {
System.out.println(totalNQueens(8));
}
public static int totalNQueens(int n) {
int[] queenList = new int[n];
return placeQueen(queenList, 0, n);
}
// 递归回溯8皇后,关键记录下到达了哪一行了
public static int placeQueen(int[] queenList, int row, int n){
// Base Case, 已经完成任务了
if(row == n){
return 1;
}
int cnt = 0;
// 开始这一行的查找
// 遍历第row行的所有列,测试哪一个位置是安全的
for(int col=0; col<n; col++){
if(isSafe(queenList, row, col)){
queenList[row] = col;
cnt += placeQueen(queenList, row+1, n);
}
}
return cnt;
}
// 判断是否坐标(row,col)的位置是安全的(检查行,列,正反对角线)
// queenList里面存放行,列坐标pair,即queenList[row] = col
public static boolean isSafe(int[] queenList, int row, int col){
for(int preRow=0; preRow<row; preRow++){
int preCol = queenList[preRow];
if(preRow == row){ // 理论上不必检查,因为preRow是总是小于row的
return false;
}
if(preCol == col){ // 检查是否在同一列
return false;
}
if(row-preRow == col-preCol){ // 反对角线
return false;
}
if(preRow+preCol == row+col){ // 正对角线
return false;
}
}
return true;
}
}
注意N Queen和Sudoku solver不一样的是N Queen可以就用int[] pos一维数组即可,而sudoku则用char[][] boarder二维数组
public class Solution {
public int totalNQueens(int n) {
int[] pos = new int[n];
int[] cnt = {0};
Arrays.fill(pos, -1); // initialize to -1
rec(pos, 0, cnt);
return cnt[0];
}
// (row, pos[row])
public void rec(int[] pos, int row, int[] cnt) {
if(row >= pos.length) {
cnt[0]++;
return;
}
for(int col=0; col<pos.length; col++) {
pos[row] = col;
if(isValid(pos, row)) {
rec(pos, row+1, cnt);
}
pos[row] = -1;
}
}
public boolean isValid(int[] pos, int row) {
for(int i=0; i<pos.length; i++) {
if(pos[i] == -1) { // notice we need to skip initialized status
continue;
}
if(i != row && pos[i] == pos[row]) {
return false;
}
if(i != row && Math.abs(row-i) == Math.abs(pos[row]-pos[i])) {
return false;
}
}
return true;
}
}