2

I have written some code which runs fine except the fact that it is also finding duplicate board states. I want to have minimal changes in my code so that it can find only unique board states. I'm pasting my code below:

class Solution {
    
    List<List<String>> arrangements = new ArrayList<>();
    
    public List<List<String>> solveNQueens(int n) {
        int visited[][] = new int[n][n];
        char board[][] = new char[n][n];
        solve(board,visited,0);
        return arrangements;
    }
    
    public boolean solve(char board[][], int visited[][], int queens) {
        if(queens == board.length) {
            return true;
        }
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < board.length; j++) {
                if(visited[i][j] == 0) {
                    changePosition(visited,i,j,1); //set
                    board[i][j] = 'Q';
                    if(solve(board,visited,queens+1)) {
                        save(board);
                    }
                    changePosition(visited,i,j,-1); // unset
                    board[i][j] = '.';
                }
            }
        }
        return false;
    }
    
    public void save(char board[][]) {
        List<String> state = new ArrayList<>();
        for(int i = 0; i < board.length; i++) {
            String row = "";
            for(int j = 0; j < board.length; j++) {
                if(board[i][j] == 'Q'){
                    row += 'Q';
                }else{
                    row += '.';
                }
            }
            state.add(row);
        }
        arrangements.add(state);
    }
    
    public void changePosition(int visited[][], int i, int j, int val) {
        // setting the column
        for(int k = 0; k < visited.length; k++) {
            visited[k][j] += val;
        }
        visited[i][j] -= val;
        //setting the row
        for(int k = 0; k < visited.length; k++) {
            visited[i][k] += val;
        }
        visited[i][j] -= val;
        //setting 1 diagonal
        int a = i, b = j;
        while(a < visited.length && b < visited.length) {
            visited[a][b] += val;
            a++;
            b++;
        }
        visited[i][j] -= val;
        a = i;
        b = j;
        while(a >= 0 && b >= 0) {
            visited[a][b] += val;
            a--;
            b--;
        }
        visited[i][j] -= val;
        //setting 2nd diagonal
        a = i;
        b = j;
        while(a < visited.length && b >= 0) {
            visited[a][b] += val;
            a++;
            b--;
        }
        visited[i][j] -= val;
        a = i;
        b = j;
        while(a >=0 && b < visited.length) {
            visited[a][b] += val;
            a--;
            b++;
        }
    }
}

The function solveNQueens returns all valid board states in the form of a List of board states (a board state in represented in from of a List of rows which are represented using String). Thanks in advance!

1 Answers1

1

The problem with your code is that for each queen, you try all possible board positions. This means that for n queens, every solution will be repeated n! times (the number of times the n queens can be permutated among the queen positions in the solution).

We can see this from the number of solutions your program finds for each n (reference):

  • n=4: There are 2 solutions, but your program finds 48 = 2*4! = 2*24 solutions.
  • n=5: There are 10 solutions, but your program finds 1200 = 10*5!=10*120 solutions.
  • n=6: There are 4 solutions, but your program finds 2880 = 4*6! = 4*720 solutions.
  • ...

This can be fixed easily: Instead of trying all possible board positions for each queen, restrict every queen to a fixed column and only try the positions within this column. This way, no duplicate board positions can be found.

In your solve method, remove the inner for loop and instead set the j coordinate to be the number of the queen (meaning queen 0 will be in column 0, queen 1 will be in column 1, and so on):

  public boolean solve(char board[][], int visited[][], int queens) {
    if (queens == board.length) {
      return true;
    }
    for (int i = 0; i < board.length; i++) {
      int j = queens;
      ...