leetcode51 (Queen N: Backtracking)

The n queen problem studies how to place n queens on an n×n chessboard and make the queens unable to attack each other.
Given an integer n, return solutions to all different n queen problems.

Each solution includes a clear pawn placement plan for the n-queen problem, where'Q' and'.' represent the queen and the empty position respectively.

Example:
Input: 4
Output: [
[".Q…", // Solution 1
“…Q”,
“Q…”,
“…Q.”],

["…Q.", // Solution 2
“Q…”,
“…Q”,
“.Q…”]
]
Explanation: 4 There are two different solutions to the queen problem.

Solution: Use the backtracking method to traverse all possible situations to find out the situation that meets the requirements. In order to reduce the time complexity, we can increase some conditional restrictions while traversing-whenever we place a queen in a position, we You can set the left slash, right slash, vertical direction and horizontal direction as the "forbidden zone", that is, the position of the queen cannot be placed. At the same time, for the convenience of backtracking, we place the queen in horizontal units from top to bottom, each line Put one (because n queens are placed in n ∗ * n is on the chessboard, so one must be placed in each row).

import java.util.*;
class Solution {
    
    
    private final Stack<Integer>stack=new Stack<>();
    private final List<List<String>>res=new ArrayList<>();
    public List<List<String>> solveNQueens(int n) {
    
    
          //二维布尔型数组记录不能放置皇后的位置
          boolean[][] banned=new boolean[n][n];
          DFS(banned,0);
          return res;
    }
    private void DFS(boolean[][]banned,int row){
    
    
        if(stack.size()== banned.length){
    
    
                 getMap(stack,res);
                 return;
        }

        Queue<int[]>save=new LinkedList<>();
        int len=banned[row].length;
        //在每一行从左到右一次尝试放皇后
        for(int i=0;i<len;i++){
    
    
            if(!banned[row][i]) {
    
    
                stack.add(i);
                 //将该行往下的每一行不能放置皇后的位置都设置为true
                for (int j = row; j < banned.length; j++) {
    
    
                    if(!banned[j][i ]) {
    
    
                        save.add(new int[]{
    
    j, i});
                        banned[j][i] = true;
                    }
                    int k = j - row;
                    
                     if (i + k < len&&!banned[j][i + k]) {
    
    
                        save.add(new int[]{
    
    j, i + k});
                        banned[j][i + k] = true;
                    }
                    if (i - k >= 0&&!banned[j][i - k]) {
    
    
                        save.add(new int[]{
    
    j, i - k});
                        banned[j][i - k] = true;
                    }
                }
                DFS(banned, row + 1);
                stack.pop();
                //还原
                while(!save.isEmpty()){
    
    
                    int[] temp=save.poll();
                    banned[temp[0]][temp[1]]=false;
                }
            }

        }
    }
    private void getMap(Stack<Integer>stack,List<List<String>>res){
    
    
        int size=stack.size();
        List<String>map=new ArrayList<>();
        for(int x:stack){
    
    
            StringBuilder row=new StringBuilder();
            for(int i=0;i<size;i++){
    
    
                if(i!=x)
                    row.append(".");
                else
                    row.append("Q");
            }
            map.add(row.toString());
        }
        res.add(map);
    }

   
}

Optimization: We can optimize the code through the rules of the chessboard-in fact, every slash on the chessboard has a unique number for that slash. For example, the difference between the horizontal and vertical coordinates of a point on the same right slash is a unique constant , The sum of the horizontal and vertical coordinates of the points on the left oblique line is a unique constant, and different columns can be distinguished by column-labeled numbers. Therefore, we no longer need to use a two-dimensional array to store the points that cannot be placed on the queen, directly use a number To indicate that a queen cannot be placed on a certain diagonal line or on a certain column.

import java.util.*;
class Solution {
    
    
    private final Stack<Integer>stack=new Stack<>();
    private final List<List<String>>res=new ArrayList<>();
    private final Set<Integer>left=new HashSet<>();
    private final Set<Integer>right=new HashSet<>();
    private final Set<Integer>down=new HashSet<>();
    public List<List<String>> solveNQueens(int n) {
    
    
          boolean[][] banned=new boolean[n][n];
          backTrace(0,n);
          return res;
    }
    private void backTrace(int column,int len){
    
    
        if(stack.size()==len){
    
    
                 getMap(stack,res);
                 return;
        }
        for(int i=0;i<len;i++){
    
    
           int rightKey=column-i;
           int leftKey=column+i;
           if(!right.contains(rightKey)&&!left.contains(leftKey)&&!down.contains(i)) {
    
    
               right.add(rightKey);
               left.add(leftKey);
               down.add(i);
               stack.push(i);
               backTrace(column+1,len);
               right.remove(rightKey);
               left.remove(leftKey);
               down.remove(i);
               stack.pop();
           }
        }
    }
    private void getMap(Stack<Integer>stack,List<List<String>>res){
    
    
        int size=stack.size();
        List<String>map=new ArrayList<>();
        for(int x:stack){
    
    
            StringBuilder row=new StringBuilder();
            for(int i=0;i<size;i++){
    
    
                if(i!=x)
                    row.append(".");
                else
                    row.append("Q");
            }
            map.add(row.toString());
        }
        res.add(map);
    }

}

Guess you like

Origin blog.csdn.net/CY2333333/article/details/108397198