Search code examples
javaarraylistn-queens

ArrayList won't hold objects correctly (N Queens example)


I've solved the N Queens problem to return an ArrayList that holds all the possible solutions.

I know that the algorithm itself is correct because it prints the correct solutions out. However, when I iterate through the returned ArrayList, I don't see the correct solutions. I just see empty grids (i.e. 4 rows of 0s).

Could anyone tell me why I'm printing the correct answers in the program but they're not correctly being added to the ArrayList?

Here's my code to give context, but you should really pay attention to the first if statement in queens() where printGrid() prints the correct solution which I (assumedly) add to my list. However, when I iterate through the list in the main method, I get 0s.

public class Question {

    static int GRID_SIZE = 4;

    public static ArrayList<int[][]> queens(int[][] grid) {
        ArrayList<int[][]> list = new ArrayList<int[][]>();

        queens(grid, 0, list);

        return list;
    }

    public static void queens(int[][] grid, int row, ArrayList<int[][]> list) {

        // if you reached the end of the grid successfully
        if (row == GRID_SIZE) {

            //print grid - shows correct solution
            printGrid(grid);

            //adding correct solution to list?
            list.add(grid);

        }

        else {
            //iterate through columns
            for (int i = 0; i < GRID_SIZE; i++) {

                // check if the spot is free
                if (valid(grid, row, i)) {
                    // place queen
                    grid[row][i] = 1;

                    // move onto next row
                    queens(grid, row + 1, list);

                    //backtrack if placement of queen does not allow successful solution
                    grid[row][i] = 0;
                }
            }
        }
    }

    // need to check previous rows to see if it's safe to place queen
    public static boolean valid(int[][] grid, int row, int col) {

        // check columns of each previous row
        for (int i = 0; i < row; i++) {
            if (grid[i][col] == 1) {
                return false;
            }
        }

        // check left diagonal
        int rowNum = row;
        int colNum = col;
        while (rowNum >= 0 && colNum >= 0) {
            if (grid[rowNum--][colNum--] == 1) {
                return false;
            }
        }

        // check right diagonals
        rowNum = row;
        colNum = col;
        while (rowNum >= 0 && colNum < GRID_SIZE) {
            if (grid[rowNum--][colNum++] == 1) {
                return false;
            }
        }

        return true;
    }

    public static void printGrid(int[][] grid) {
        System.out.println("---------");
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid.length; j++) {
                System.out.print(grid[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println("---------");
    }

    public static void main(String[] args) {
        int[][] grid = new int[GRID_SIZE][GRID_SIZE];

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid.length; j++) {
                grid[i][j] = 0;
            }
        }

        ArrayList<int[][]> list = queens(grid);

        System.out.println(list.size());

        printGrid(list.get(0));

    }
}

Here's the output:

---------
0 1 0 0 
0 0 0 1 
1 0 0 0 
0 0 1 0 
---------
---------
0 0 1 0 
1 0 0 0 
0 0 0 1 
0 1 0 0 
---------
ITERATING THROUGH ARRAYLIST:
---------
0 0 0 0 
0 0 0 0 
0 0 0 0 
0 0 0 0 
---------
---------
0 0 0 0 
0 0 0 0 
0 0 0 0 
0 0 0 0 
---------

Solution

  • You only have one array instance which you keep mutating and add it to the List multiple times. At the end, the List contains references to that single array in its final state.

    Instead of list.add(grid); you should be adding a copy of grid (note that Arrays.copyOf() or System.arraycopy() won't be enough here, since they perform shallow copy and your array is 2 dimentional).