Tuesday, January 20, 2015

N-Queens (LeetCode Backtracking)

Question: 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.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]

Idea: Brute force depth-first-search. First initial a char[][] filled with '.'s. For each row, we try to put a queen (set char[x][y]='Q') at any column. If it is valid (no conflict), place the queen then go to the next row. If we reach row==n (out of boundary), that means all the rows from 0=>n-1 are valid, append this assignment to the result.
For easier understanding, I wrote the check valid function in all the 8 directions separately: same row, same column, 2 diagonal, 2 counter- diagonal. The code presentation can be simplified by getting the distance to the boundaries first, but it will be a little bit harder to be understood. So I keep the a little bit longer but easier understood writing.

Time: O(n^n) Space: O(1)

Code:
 public class Solution {  
   public List<String[]> solveNQueens(int n) {  
     List<String[]> result=new ArrayList<String[]>();  
     if(n==0)  
       return result;  
     char[][] board=new char[n][n];  
     for(int i=0;i<n;i++)  
       Arrays.fill(board[i],'.');  
     dfs(result,board,0);  
     return result;  
   }  
   public void dfs(List<String[]> result,char[][] board,int curRow)  
   {  
     int n=board.length;  
     if(curRow==n)  
     {  
       result.add(toStringArray(board));  
       return;  
     }  
     for(int j=0;j<n;j++)  
     {  
       board[curRow][j]='Q';  
       if(isValid(board,curRow,j))  
       {  
         dfs(result,board,curRow+1);  
       }  
       board[curRow][j]='.';  
     }  
   }  
   public String[] toStringArray(char[][] board)  
   {  
     String[] result=new String[board.length];  
     for(int i=0;i<board.length;i++)  
     {  
       StringBuilder builder=new StringBuilder();  
       for(int j=0;j<board.length;j++)  
         builder.append(board[i][j]);  
       result[i]=builder.toString();  
     }  
     return result;  
   }  
   public boolean isValid(char[][] board, int x, int y)  
   {  
     int n=board.length;  
     for(int i=0;i<n;i++)  
     {  
       if(i!=x&&board[i][y]=='Q')  
         return false;  
     }  
     for(int j=0;j<n;j++)  
     {  
       if(j!=y&&board[x][j]=='Q')  
         return false;  
     }  
     for(int i=1;x+i<n&&y+i<n;i++)  
     {  
       if(board[x+i][y+i]=='Q')  
         return false;  
     }  
     for(int i=1;x-i>=0&&y-i>=0;i++)  
     {  
       if(board[x-i][y-i]=='Q')  
         return false;  
     }  
     for(int i=1;x-i>=0&&y+i<n;i++)  
     {  
       if(board[x-i][y+i]=='Q')  
         return false;  
     }  
     for(int i=1;x+i<n&&y-i>=0;i++)  
     {  
       if(board[x+i][y-i]=='Q')  
         return false;  
     }  
     return true;  
   }  
 }  

No comments:

Post a Comment