N皇后

力扣链接

N皇后是经典的回溯算法问题,去年刚学习算法时就已写过C++版,现在记录下Java版本。 (注释留着下次回顾时再补充吧)

class Solution {
    public List<List<String>> solveNQueens(int n) {
        char[][] board = new char[n][n];
        List<List<String>> res = new ArrayList<>();
        for(int i=0; i<n; i++)
            Arrays.fill(board[i],'.');
        backtrack(res,board,0);
        return res;
    }

    public void backtrack(List<List<String>> res, char[][] board, int row) {
        if(row==board.length) {
            res.add(charToList(board));
            return ;
        }
        for(int i=0; i<board.length; i++) {
            if(!isValid(board,row,i))
                continue;
            board[row][i] = 'Q';
            backtrack(res,board,row+1);
            board[row][i] = '.';
        }
    }

    public boolean isValid(char[][] board, int row, int col){
        for(int i=row-1; i>=0; i--) {
            if(board[i][col]=='Q')
                return false;
        }
        for (int i = row - 1, j = col + 1;
             i >= 0 && j < board.length; i--, j++)
        {
            if (board[i][j] == 'Q')
                return false;
        }
        for (int i = row - 1, j = col - 1;
             i >= 0 && j >= 0; i--, j--)
        {
            if (board[i][j] == 'Q')
                return false;
        }
        return true;
    }

    public List<String> charToList(char[][] board) {
        int len = board.length;
        List<String> res = new ArrayList<>();
        for(int i=0; i<len; i++) {
            res.add(new String(board[i]));
        }
        return res;
    }
}

 关于插入新Q后判断当前棋盘是否有效,可以做出优化:利用三个set,记录已饱和的列和两个对角线,用空间换时间。

class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> solutions = new ArrayList<List<String>>();
        int[] queens = new int[n];
        Arrays.fill(queens, -1);
        Set<Integer> columns = new HashSet<Integer>();
        Set<Integer> diagonals1 = new HashSet<Integer>();
        Set<Integer> diagonals2 = new HashSet<Integer>();
        backtrack(solutions, queens, n, 0, columns, diagonals1, diagonals2);
        return solutions;
    }

    public void backtrack(List<List<String>> solutions, int[] queens, int n, int row, Set<Integer> columns, Set<Integer> diagonals1, Set<Integer> diagonals2) {
        if (row == n) {
            List<String> board = generateBoard(queens, n);
            solutions.add(board);
        } else {
            for (int i = 0; i < n; i++) {
                if (columns.contains(i)) {
                    continue;
                }
                int diagonal1 = row - i;
                if (diagonals1.contains(diagonal1)) {
                    continue;
                }
                int diagonal2 = row + i;
                if (diagonals2.contains(diagonal2)) {
                    continue;
                }
                queens[row] = i;
                columns.add(i);
                diagonals1.add(diagonal1);
                diagonals2.add(diagonal2);
                backtrack(solutions, queens, n, row + 1, columns, diagonals1, diagonals2);
                queens[row] = -1;
                columns.remove(i);
                diagonals1.remove(diagonal1);
                diagonals2.remove(diagonal2);
            }
        }
    }

    public List<String> generateBoard(int[] queens, int n) {
        List<String> board = new ArrayList<String>();
        for (int i = 0; i < n; i++) {
            char[] row = new char[n];
            Arrays.fill(row, '.');
            row[queens[i]] = 'Q';
            board.add(new String(row));
        }
        return board;
    }
}

此外还有位运算的优化方法,尚未研究,有待补充。

原文地址:https://www.cnblogs.com/faded828x/p/14511374.html