是上一题的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; } }