面试题 08.12. 八皇后--回溯算法

LeetCode

面试题 08.12. 八皇后

设计一种算法,打印 N 皇后在 N × N 棋盘上的各种摆法,其中每个皇后都不同行、不同列,也不在对角线上。这里的“对角线”指的是所有的对角线,不只是平分整个棋盘的那两条对角线。

注意:本题相对原题做了扩展

示例:

输入:4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释: 4 皇后问题存在如下两个不同的解法。
[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]

解法:回溯法

解题思路:

要找到这N个皇后,根据要求,每个皇后不能在同一行同一列同一对角线,因此,当我们在选择皇后的位置时,必须要找到它所有对角线和列上是否有其它皇后,根据

col + (currRow - row) 为一个位置的右上角
col - (currRow - row) 为一个位置的左上角

我们可以得到下面的代码

for (int col = 0; col < len; col++) {
    //判断这个位置是否合适
    boolean isok = true;
    for (int row = 0; row < currRow; row++) {
        //竖的有Q
        if (nums[row][col] == 'Q') 
        {
            isok = false;
            break;
        }
        //判断对角线
        if (col + (currRow - row) < len && nums[row][col + (currRow - row)] == 'Q') 
        {
            isok = false;
            break;
        }
        if (col - (currRow - row) >= 0 && nums[row][col - (currRow - row)] == 'Q') 
        {
            isok = false;
            break;
        }
    }
    if (!isok) 
    {
        continue;
    }
    //满足条件
    nums[currRow][col] = 'Q';
    backtrack(nums, currRow + 1, ans);
    nums[currRow][col] = '.';
}

而回溯的思想在于,我们从第一行开始找第一个皇后的位置,然后再找第二行,当当前皇后在当前行没有位置可放时,就回溯到上一个皇后,重新找上一个皇后的位置

完整代码如下:

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

    private void backtrack(char[][] nums, int currRow, List> ans) 
    {
   		//currRow表示第几行,同时也表示了找第几个皇后
        int len = nums.length;
        if (len == currRow) //所有皇后都找完了
         {
            List path2 = new ArrayList<>();
            for (int i = 0; i < len; i++) 
            {
                path2.add(String.valueOf(nums[i]));
            }
            ans.add(path2);
            return;
        }
        //将数组的结果变为列表加入结果集
        for (int col = 0; col < len; col++) 
        {
            //判断这个位置是否合适
            boolean isok = true;
            for (int row = 0; row < currRow; row++) 
            {
                //竖的有Q
                if (nums[row][col] == 'Q') 
                {
                    isok = false;
                    break;
                }
                //判断对角线
                if (col + (currRow - row) < len && nums[row][col + (currRow - row)] == 'Q')
                 {
                    isok = false;
                    break;
                }
                if (col - (currRow - row) >= 0 && nums[row][col - (currRow - row)] == 'Q') 
                {
                    isok = false;
                    break;
                }
            }
            if (!isok) 
            {
                continue;
            }
            //满足条件
            nums[currRow][col] = 'Q';
            backtrack(nums, currRow + 1, ans);
            nums[currRow][col] = '.'; //回溯
        }
    }
}

题目以及解法来源

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/eight-queens-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

你可能感兴趣的:(回溯算法)