leetcode-pp / 91alg-6-daily-check

91 算法第六期打卡仓库
28 stars 0 forks source link

【Day 49 】2022-01-29 - 52. N 皇后 II #59

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

52. N 皇后 II

入选理由

暂无

题目地址

https://leetcode-cn.com/problems/n-queens-ii/

前置知识

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。

示例 1:


![](https://tva1.sinaimg.cn/large/008i3skNly1gvucyhyefdj30k208yq3f.jpg)

输入:n = 4 输出:2 解释:如上图所示,4 皇后问题存在两个不同的解法。 示例 2:

输入:n = 1 输出:1  

提示:

1 <= n <= 9 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

yetfan commented 2 years ago

思路 从0行开始,遍历每一个位置,尝试放置皇后, 通过检查之前存储的皇后们的位置,查看是否在一行,是否在一个对角线上 如果确定一个位置,则继续尝试放置下一个皇后,直到成功放满n个皇后,结果+1

代码

class Solution:
    def totalNQueens(self, n: int) -> int:
        self.res = 0
        self.n = n
        self.find_queen()
        return self.res

    def find_queen(self, row=0, prior=[]):
        if row == self.n:
            self.res += 1

        for i in range(self.n):
            if i not in prior:  # 和之前的不在一列中
                for index, pos in enumerate(prior):  
                    if row-index == abs(i-pos):  # 检测之前的位置是否在斜线
                        break
                else:
                    self.find_queen(row + 1, prior + [i])  # 通过检查,开始寻找下一行的位置
                    # 这块不要直接更改row和prior的值,传值即可,因为递归失败的话需要回溯,继续用原来的参数检查下一个位置的可行性。

复杂度 时间 O(n!) 空间 O(n)

LinnSky commented 2 years ago

思路

位运算

代码

   var totalNQueens = function(n) {
      if(n < 1) return
      let count = 0
      dfs(n, 0, 0, 0, 0)
      return count

      function dfs(n, row, cols, diag1, diag2) {
          if(row >= n) {
              count += 1
              return
          }
          let bits = (~(cols | diag1 | diag2)) & ((1 << n) - 1)
          while(bits) {
              let p = bits & -bits
              bits = bits & (bits - 1)
              dfs(n, row + 1, cols | p, (diag1 | p) << 1, (diag2 | p) >>> 1)
          }
      }
  };
feifan-bai commented 2 years ago

思路

  1. 回溯

代码

class Solution:
    def totalNQueens(self, n: int) -> int:
        def backtrack(row: int) -> int:
            if row == n:
                return 1
            else:
                count = 0
                for i in range(n):
                    if i in columns or row - i in diagonal1 or row + i in diagonal2:
                        continue
                    columns.add(i)
                    diagonal1.add(row - i)
                    diagonal2.add(row + i)
                    count += backtrack(row + 1)
                    columns.remove(i)
                    diagonal1.remove(row - i)
                    diagonal2.remove(row + i)
                return count

        columns = set()
        diagonal1 = set()
        diagonal2 = set()
        return backtrack(0)

复杂度分析

zhangzz2015 commented 2 years ago

思路

关键点

代码

C++ Code:


class Solution {
public:
    int totalNQueens(int n) {

    // Time O(n^n)  Space O(n)  Use 15 min.        
        vector<int> onePath;
        int ret=0; 

        backTrac(n, onePath, 0, ret); 
        return ret; 

    }

    void backTrac(int n, vector<int>& onePath, int row,  int& ret)
    {
        if(onePath.size()==n) // Find one possible solution. 
        {
            ret++; 
            return;             
        }            
        for(int col =0; col <n; col++) // loop every col and see if it is valid. 
        {
            if(isValid(onePath, row, col))
            {
                onePath.push_back(col); 
                backTrac(n, onePath, row+1, ret);
                onePath.pop_back(); 
            }
        }
    }

    bool isValid(vector<int>& onePath, int irow, int icol)
    {
        // vertical
        for(int i=0; i< onePath.size(); i++)
        {
            if(onePath[i] == icol)
                return false; 
            if(onePath[i]+(irow-i) == icol)
                return false; 
            if(onePath[i]-(irow-i) == icol)
                return false; 
        }        
        return true;         
    }
};
ZacheryCao commented 2 years ago

Idea

Backtracking

Code

class Solution {
public:
    int totalNQueens(int n) {
        set<int> cols, diags, anti_diags;
        return backtracking(0, cols, diags, anti_diags, n);
    }

    int backtracking(int row, set<int> cols, set<int> diags, set<int> anti_diags, int n){
        if(row == n) return 1;
        int solutions = 0;
        for(int col = 0; col<n; col++){
            int cur_diag = row-col;
            int cur_anti_diag = row+col;
            if(cols.find(col) != cols.end() || diags.find(cur_diag) != diags.end()|| anti_diags.find(cur_anti_diag) != anti_diags.end()){
                continue;
            }
            cols.insert(col);
            anti_diags.insert(cur_anti_diag);
            diags.insert(cur_diag);
            solutions += backtracking(row+1,cols, diags, anti_diags, n);
            cols.erase(col);
            anti_diags.erase(cur_anti_diag);
            diags.erase(cur_diag);
        }
        return solutions;
    }
};

Complexity:

Time: O(N!) Space: O(N)

CoreJa commented 2 years ago

思路

代码

    def totalNQueens(self, n: int) -> int:
        col=set()
        diagonal_45=set()
        diagonal_135=set()
        ans=0
        def dfs(dep,i):
            nonlocal ans
            if dep==0:
                ans+=1
                return
            for j in range(n):
                if j not in col and i-j not in diagonal_45 and i+j not in diagonal_135:
                    col.add(j)
                    diagonal_45.add(i-j)
                    diagonal_135.add(i+j)
                    dfs(dep-1,i+1)
                    col.remove(j)
                    diagonal_45.remove(i-j)
                    diagonal_135.remove(i+j)

        dfs(n,0)
        return ans
RocJeMaintiendrai commented 2 years ago
class Solution {
    public int res = 0;
    Set<Integer> col = new HashSet<>();
    Set<Integer> diff = new HashSet<>();
    Set<Integer> sum = new HashSet<>();

    public int totalNQueens(int n) {
        if(n <= 0) return res;
        dfs(0, n);
        return res;

    }

    private void dfs(int level, int n) {
        if(level == n) {
            res++;
            return;
        }
        //row not equal
        for(int i = 0; i < n; i++) {
            if(!col.contains(i) && !diff.contains(level - i) && !sum.contains(level + i)) {
                col.add(i);
                diff.add(level - i);
                sum.add(level + i);
                dfs(level + 1, n);
                col.remove(i);
                diff.remove(level - i);
                sum.remove(level + i);
            }
        }
    }
}

复杂度分析

moirobinzhang commented 2 years ago

Code:

public class Solution {

public int res;

public int TotalNQueens(int n) {
    res = 0;
    List<int> boardCols = new List<int>();

    DFSHelper(boardCols, n);

    return res;
}

public void DFSHelper(List<int> boardCols, int n)
{
    if (boardCols.Count == n)
    {
        res++;
        return;
    }

    for(int col = 0; col < n; col++ )
    {
        if (!IsValid(boardCols, col))
            continue;

        boardCols.Add(col);
        DFSHelper(boardCols, n);
        boardCols.RemoveAt(boardCols.Count - 1);
    }        
}

public bool IsValid(List<int> boardCols, int colIndex)
{
    int row = boardCols.Count;

    for (int rowIndex = 0; rowIndex < row; rowIndex++)
    {
        if (boardCols[rowIndex] == colIndex)
            return false;

        if (rowIndex + boardCols[rowIndex] == row + colIndex)
            return false;           

        if (rowIndex - boardCols[rowIndex] == row - colIndex)
            return false;                          
    }

    return true;        
}

}

yan0327 commented 2 years ago

思路: 回溯+位运算

func totalNQueens(n int) int {
    out := 0
    var dfs func(row int,col int,diag1 int,diag2 int) 
    dfs = func(row int,col int,diag1 int,diag2 int) {
        if row == n{
            out++
            return 
        }
        possible := (1<<n-1)&^(col|diag1|diag2)
        for possible>0{
            choose := possible&(-possible)
            dfs(row+1,choose|col,(choose|diag1)<<1,(choose|diag2)>>1) 
            possible &= (possible-1)
        }
    }
    dfs(0,0,0,0)
    return out
}
Yrtryannn commented 2 years ago
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;
    }
xinhaoyi commented 2 years ago

52. N皇后 II

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。

思路一

位运算 + dfs

两个位运算操作

1.x & -x。

这个操作可以保留最后一位1,而其他位都会清零。比如,一个8位数,00110110.进行了这个操作后就会变为00000010.我在这里想了很久,也没明白原因,后来发现原来是之前学的东西都还给了老师。。。这里的关键是:计算机存储数的时候存储的是补码,正数的补码是其本身,而负数的补码是其反码加1.因此,00110110加一个负号以后就变成了10110110(姑且认为最高位是符号位),其反码为11001001,补码为11001010。这个跟原来的数按位与后就是00000010

2.x & (x - 1)。将最后一位1变为0。可以先这么考虑一下,最低位如果是1,减1后就变为了0,按位与后,其他位不发生变化,最低位清为0.现在考虑更复杂的情况,如果最低位是0,那么减1后,这个0就变为了1,并且向高位借位,直到遇到第一个1,这个1会因为之前的借位变成0,此时借位清0,更高位的数据就不会发生变化。这样按位与后,最低位的1就变成了0,而其他的数并没有变化。

代码

class Solution {
    int res=0;
    public int totalNQueens(int n) {
        dfs(n,0,0,0,0);//位中0表示能放皇后
        return res;
    }

    //n表示多少个皇后,row表示放第几行的皇后,col中位为1表示不能放皇后,ld和rd同理
    public void dfs(int n,int row,int col,int ld,int rd){
        if(row==n){
            res++;
            return;
        }
        //col|ld|rd找出不可以放置皇后的位置(1表示),取反之后表示1代表能放皇后的位置
        //(1<<n)-1先把1变成1后面n个0,减1之后就是低位存在n个连续的1,即能放皇后
        //这里一开始col,ld,rd都是0,但实际上是n位的0
        int canQueens=~(col|ld|rd)&((1<<n)-1);

        //没有放完全部皇后的位置
        while(canQueens>0){
            int place=canQueens&(-canQueens);//取最低位的1,表示选中皇后的位置,比如010110变成了010010
            dfs(n,row+1,col|place,(ld|place)<<1,(rd|place)>>1);
            //ROW+1表示下一行,col|place表示目前已经放置了皇后的列(1表示),后面的皇后不能放这些列1
            //ld表示到第row行时由于对角线(左下)产生的不能放皇后的位置,
            //(ld|place)<<1表示当前已放置皇后到第row+1行所产生的不能放皇后的位置
            //rd即(右下)同理

            canQueens&=(canQueens-1);//当前行的皇后少了一个选择(canQueens中最后那个1)
        }

    }
}

复杂度分析

时间复杂度:$O(n!)$

空间复杂度:$O(n)$

Tesla-1i commented 2 years ago
class Solution:
    def totalNQueens(self, n: int) -> int:
        def backtrack(row: int) -> int:
            if row == n:
                return 1
            else:
                count = 0
                for i in range(n):
                    if i in columns or row - i in diagonal1 or row + i in diagonal2:
                        continue
                    columns.add(i)
                    diagonal1.add(row - i)
                    diagonal2.add(row + i)
                    count += backtrack(row + 1)
                    columns.remove(i)
                    diagonal1.remove(row - i)
                    diagonal2.remove(row + i)
                return count

        columns = set()
        diagonal1 = set()
        diagonal2 = set()
        return backtrack(0)
Hacker90 commented 2 years ago

思路: 回溯+位运算

func totalNQueens(n int) int { out := 0 var dfs func(row int,col int,diag1 int,diag2 int) dfs = func(row int,col int,diag1 int,diag2 int) { if row == n{ out++ return } possible := (1<<n-1)&^(col|diag1|diag2) for possible>0{ choose := possible&(-possible) dfs(row+1,choose|col,(choose|diag1)<<1,(choose|diag2)>>1) possible &= (possible-1) } } dfs(0,0,0,0) return out }

z1ggy-o commented 2 years ago

思路

回溯。

不能攻击的定义是:在同一行,同一列,同一斜线上只有一个棋子。

假设我们一个一个的摆棋子,当第一行摆上一个棋子之后,这一行就再不能放棋子了。 那么我们就可以将问题变为,在每一行放一个棋子,看把它放在哪个列可行。

代码

CPP

class Solution {
public:
    int totalNQueens(int n) {
        unordered_set<int> col, diag1, diag2;
        return backtrack(n, 0, col, diag1, diag2);
    }
private:
    int backtrack(int n, int row, unordered_set<int>& col, unordered_set<int>& diag1, unordered_set<int>& diag2)
    /*
     * @n: number of the queens, also the size of the board
     * @row: current row number
     * @col: a set that stores already used columns
     * @diag1: a set that stores positions that are used in the left to right diagonal
     * @diag2: right to left diagonal
     */
     {
         if (row == n) {  // the last row, all other columns are used
             return 1;
         }

         int count = 0;
         for (int i = 0; i < n; i++) {
             if (col.find(i) != col.end()) {
                 // this column is used
                 continue;
             }
             // left to right: row_idx - col_idx are the same
             int diagonal1 = row - i;
             if (diag1.find(diagonal1) != diag1.end()) {
                 continue;
             }
             // right to left: row_idx + col_idx are the same
             int diagonal2 = row + i;
             if (diag2.find(diagonal2) != diag2.end()) {
                 continue;
             }
            // mark this position
             col.insert(i);
             diag1.insert(diagonal1);
             diag2.insert(diagonal2);

             count += backtrack(n, row+1, col, diag1, diag2);

             // states under this root are all checked, unmark
             col.erase(i);
             diag1.erase(diagonal1);
             diag2.erase(diagonal2);
         }

         return count;
     }
};

复杂度分析

hdyhdy commented 2 years ago

思路:回溯 ··· func totalNQueens(n int) int { count := 0 // 当n=2,3时,n皇后是无解的 if n > 1 && n <= 3 { return count } // n=1时,有唯一解 if n == 1 { return 1 }

//初始化
board := make([][]string, n)
for i := 0; i < n; i++ {
    board[i] = make([]string, n)
}
for i := 0; i < n; i++ {
    for j := 0; j < n; j++ {
        board[i][j] = "."
    }
}

var backTrack func(int, [][]string)
backTrack = func(row int, board [][]string) {
    // 递归终止条件,如果递归到最后一行,则得到一个解
    if row == n {
        count++
        return
    }
    for column := 0; column < n; column++ {
        // 如果不满足皇后们的约束条件,则跳过本次循环
        if !IsValid(row, column, n, board) {
            continue
        }
        // 如果满足约束条件, 则在该位置放置一个皇后
        board[row][column] = "Q"
        // 递归
        backTrack(row+1, board)
        // 回溯
        board[row][column] = "."
    }
}
backTrack(0, board)
return count

}

// IsValid 判断在board[row][column]位置放置皇后是否满足所有约束条件 func IsValid(row, column, n int, board [][]string) bool { // 由于单层搜索时,每一层递归都只会选同一行里的一个元素,所以行不用去重了。 // 检查列 for i := 0; i < row; i++ { if board[i][column] == "Q" { return false } } // 检查45度对角线 for i, j := row-1, column-1; i >= 0 && j >= 0; i, j = i-1, j-1 { if board[i][j] == "Q" { return false } } // 检查135度对角线 for i, j := row-1, column+1; i >= 0 && j < n; i, j = i-1, j+1 { if board[i][j] == "Q" { return false } } return true } ···

pwqgithub-cqu commented 2 years ago

思路: 回溯 func totalNQueens(n int) int { out := 0 var dfs func(row int,col int,diag1 int,diag2 int) dfs = func(row int,col int,diag1 int,diag2 int) { if row == n{ out++ return } possible := (1<<n-1)&^(col|diag1|diag2) for possible>0{ choose := possible&(-possible) dfs(row+1,choose|col,(choose|diag1)<<1,(choose|diag2)>>1) possible &= (possible-1) } } dfs(0,0,0,0) return out } 时间复杂度:O(N) 空间复杂度:O(N)

zhiyuanpeng commented 2 years ago
class Solution:
    def totalNQueens(self, n):
        def backtrack(row, diagonals, anti_diagonals, cols):
            # Base case - N queens have been placed
            if row == n:
                return 1

            solutions = 0
            for col in range(n):
                curr_diagonal = row - col
                curr_anti_diagonal = row + col
                # If the queen is not placeable
                if (col in cols 
                      or curr_diagonal in diagonals 
                      or curr_anti_diagonal in anti_diagonals):
                    continue

                # "Add" the queen to the board
                cols.add(col)
                diagonals.add(curr_diagonal)
                anti_diagonals.add(curr_anti_diagonal)

                # Move on to the next row with the updated board state
                solutions += backtrack(row + 1, diagonals, anti_diagonals, cols)

                # "Remove" the queen from the board since we have already
                # explored all valid paths using the above function call
                cols.remove(col)
                diagonals.remove(curr_diagonal)
                anti_diagonals.remove(curr_anti_diagonal)

            return solutions

        return backtrack(0, set(), set(), set())
ZJP1483469269 commented 2 years ago
from collections import defaultdict
class Solution:
    def totalNQueens(self, n: int) -> int:
        global dicy ,dic1,dic2,res

        dicy = defaultdict(int)
        dic1 = defaultdict(int)
        dic2 = defaultdict(int)
        def backtrack(x):
            global dicy ,dic1,dic2 , res
            if x == n:
                res += 1

            for j in range(n):
                if dicy[j] != 0 or dic1[x+j] != 0 or dic2[x - j ] != 0:
                    continue
                dicy[j] , dic1[x+j] , dic2[x - j] = 1 , 1 , 1 
                backtrack(x + 1)
                dicy[j] , dic1[x+j] , dic2[x - j] = 0 , 0 , 0 

        res = 0
        backtrack(0)
        return res
JudyZhou95 commented 2 years ago

代码

class Solution:
    def totalNQueens(self, n: int) -> int:
        self.res = 0

        #flag for column (n), 2 sets of diagonals (2n-1) * 2
        self.flag = [0] * (5*n - 2)

        self.backtrack(0, n)
        return self.res

    def backtrack(self, row, n):
        if row == n:
            self.res += 1
            return 

        for col in range(n):
            if self.flag[col] or self.flag[2*n+col-row-1] or self.flag[3*n+row+col-1]:
                continue

            self.flag[col] = 1
            self.flag[2*n+col-row-1] = 1
            self.flag[3*n+row+col-1] = 1

            self.backtrack(row+1, n)

            self.flag[col] = 0
            self.flag[2*n+col-row-1] = 0
            self.flag[3*n+row+col-1] = 0

复杂度

TC: O(N!) SC: O(N)

zhiyuanpeng commented 2 years ago
class Solution:
    def totalNQueens(self, n):
        def backtrack(row, diagonals, anti_diagonals, cols):
            # Base case - N queens have been placed
            if row == n:
                return 1

            solutions = 0
            for col in range(n):
                curr_diagonal = row - col
                curr_anti_diagonal = row + col
                # If the queen is not placeable
                if (col in cols 
                      or curr_diagonal in diagonals 
                      or curr_anti_diagonal in anti_diagonals):
                    continue

                # "Add" the queen to the board
                cols.add(col)
                diagonals.add(curr_diagonal)
                anti_diagonals.add(curr_anti_diagonal)

                # Move on to the next row with the updated board state
                solutions += backtrack(row + 1, diagonals, anti_diagonals, cols)

                # "Remove" the queen from the board since we have already
                # explored all valid paths using the above function call
                cols.remove(col)
                diagonals.remove(curr_diagonal)
                anti_diagonals.remove(curr_anti_diagonal)

            return solutions

        return backtrack(0, set(), set(), set())
Flower-F commented 2 years ago

解题思路

回溯

代码

/**
 * @param {number} n
 * @return {number}
 */
var totalNQueens = function (n) {
  const board = new Array(n).fill('.').map(() => new Array(n).fill('.'));
  let res = 0;
  backtrack(0);
  return res;

  function backtrack(row) {
    if (row === n) {
      res++;
      return;
    }

    for (let col = 0; col < n; col++) {
      if (!isValid(row, col)) {
        continue;
      }
      board[row][col] = 'Q';
      backtrack(row + 1);
      board[row][col] = '.';
    }
  }

  function isValid(row, col) {
    // 因为是从上往下一行一行放的,所以不需要下方的行
    for (let i = 0; i < row; i++) {
      for (let j = 0; j < n; j++) {
        // 如果发现了 Q,并且和自己同列或同对角线
        // 判断同对角线,使用 |y1 - y2| === |x1 - x2|
        if (board[i][j] === 'Q') {
          if (j === col || Math.abs(i - row) === Math.abs(j - col)) {
            return false;
          }
        }
      }
    }
    return true;
  }
};

复杂度

时间:O(N!) 空间:O(N^2)

haixiaolu commented 2 years ago

思路

回溯: 就是比暴力还暴力的解法, 各种尝试,不行就返回 本题最主要的就是怎么才能找到每个位置的对角线

代码 / Python

class Solution:
    def totalNQueens(self, n: int) -> int:
        columns = set()
        posDiag = set() # (r + c) # 上升对角线 /
        negDiag = set() # (r - c) # 下降对角线 \

        def backtrack(row):
            if row == n:
                return 1
            else:
                count = 0
                for col in range(n):
                    if col in columns or (row + col) in posDiag or (row - col) in negDiag:
                        continue

                    columns.add(col)
                    posDiag.add(row + col)
                    negDiag.add(row - col)
                    count += backtrack(row + 1)  # 51题, board[col][row] = 'Q'

                    columns.remove(col)
                    posDiag.remove(row + col)
                    negDiag.remove(row - col)

                return count 
        return backtrack(0)

复杂度分析

shamworld commented 2 years ago
var totalNQueens = function(n) {
let res = 0;
    function dfs(row, col, dlr, dll) {
        if (row === n) return res++;
        for (let i = 0; i < n; i++) {
            const _col = 1 << i, _dlr = 1 << (i - row + n), _dll = 1 << (i + row);
            if ((col & _col) !== 0 || (dlr & _dlr) !== 0 || (dll & _dll) !== 0) continue;
            dfs(row + 1, col | _col, dlr | _dlr, dll | _dll);
        }
    }
    dfs(0, 0, 0, 0)
    return res;
};
rzhao010 commented 2 years ago

Thoughts Using three sets to check if any queen exist in the column, and two diagonals. Need to turn the status back after backtrack

Code

class Solution {
    public int totalNQueens(int n) {
        Set<Integer> columns = new HashSet<>();
        Set<Integer> diagonals1 = new HashSet<>();
        Set<Integer> diagonals2 = new HashSet<>();
        return backtrack(n, 0, columns, diagonals1, diagonals2);
    }

    private int backtrack(int n, int row, Set<Integer> columns, Set<Integer> diagonals1, Set<Integer> diagonals2) {
        if (row == n) {
            return 1;
        } else {
            int count = 0;
            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;
                }
                columns.add(i);
                diagonals1.add(diagonal1);
                diagonals2.add(diagonal2);
                count += backtrack(n, row + 1, columns, diagonals1, diagonals2);
                columns.remove(i);
                diagonals1.remove(diagonal1);
                diagonals2.remove(diagonal2);
            }
            return count;
        }
    }
}

Complexity Time: O(N!) Space: O(n)

Laurence-try commented 2 years ago
class Solution:
    def totalNQueens(self, n):
        def backtrack(row, diagonals, anti_diagonals, cols):
            # Base case - N queens have been placed
            if row == n:
                return 1

            solutions = 0
            for col in range(n):
                curr_diagonal = row - col
                curr_anti_diagonal = row + col
                # If the queen is not placeable
                if (col in cols 
                      or curr_diagonal in diagonals 
                      or curr_anti_diagonal in anti_diagonals):
                    continue

                # "Add" the queen to the board
                cols.add(col)
                diagonals.add(curr_diagonal)
                anti_diagonals.add(curr_anti_diagonal)

                # Move on to the next row with the updated board state
                solutions += backtrack(row + 1, diagonals, anti_diagonals, cols)

                # "Remove" the queen from the board since we have already
                # explored all valid paths using the above function call
                cols.remove(col)
                diagonals.remove(curr_diagonal)
                anti_diagonals.remove(curr_anti_diagonal)

            return solutions

        return backtrack(0, set(), set(), set())
zwang2244 commented 2 years ago

思路

backtracking

代码

class Solution {
    int size = 0;
    public int totalNQueens(int n) {
        size = n;
        return backtrack(0, new HashSet<Integer>(), new HashSet<Integer>(), new HashSet<Integer>());
    }

    public int backtrack(int row, HashSet<Integer> col, HashSet<Integer> diagnol, HashSet<Integer> antidiagnol){
        if(row >= size){
            return 1;
        }

        int ans = 0;
        for(int i = 0; i < size; i++){
            //check (row, i)
            if(!col.contains(i) && !diagnol.contains(row - i)
               && !antidiagnol.contains(i + row)){
                // System.out.println("1");
                col.add(i);
                diagnol.add(row - i);
                antidiagnol.add(row + i);
                ans += backtrack(row + 1, col, diagnol, antidiagnol);
                col.remove(i);
                diagnol.remove(row - i);
                antidiagnol.remove(row + i);
            }
        }
        return ans;
    }
}

复杂度分析

cszys888 commented 2 years ago
class Solution:
    def totalNQueens(self, n: int) -> int:
        self.count = 0
        self.n = n
        self.col_set = set()
        self.diag_set_1 = set()
        self.diag_set_2 = set()
        self.dfs(0)
        return self.count
    def dfs(self,row):
        if row == self.n:
            self.count += 1
            return
        for col in range(self.n):
            if col not in self.col_set and (col - row) not in self.diag_set_1 and (col + row) not in self.diag_set_2:
                self.col_set.add(col)
                self.diag_set_1.add(col - row)
                self.diag_set_2.add(col + row)
                self.dfs(row+1)
                self.col_set.remove(col)
                self.diag_set_1.remove(col - row)
                self.diag_set_2.remove(col + row)

time complexity: O(N!) space complexity: O(N)

LannyX commented 2 years ago

思路

backtracking

代码

顺便做51
class Solution {
    List<List<Integer>> res = new ArrayList<>();
    public int totalNQueens(int n) {
        char[][] chessboard = new char[n][n];
        for(char[] c : chessboard){
            Arrays.fill(c, '.');
        }
        backtrack(0, chessboard, n);
        return res.size();
    }
    void backtrack(int row, char[][] chessboard, int n){
        if(row == n){
            res.add(Array2List(chessboard));
            return;
        }
        for(int col = 0; col < n; col++){
            if(isValid(row, col, chessboard, n)){
                chessboard[row][col] = 'Q';
                backtrack(row + 1, chessboard, n);
                chessboard[row][col] = '.';
            }
        }
    }
    List Array2List(char[][] chessboard){
        List<String> list = new ArrayList<>();
        for(char[] c : chessboard){
            list.add(String.copyValueOf(c));
        }
        return list;
    }
    boolean isValid(int row, int col, char[][] chessboard, int n){
        for(int i = 0; i < row; i++){
            if(chessboard[i][col] == 'Q'){
                return false;
            }
        }
        for(int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--){
            if(chessboard[i][j] == 'Q'){
                return false;
            }
        }
        for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++){
            if(chessboard[i][j] == 'Q'){
                return false;
            }
        }
        return true;
    }
}

复杂度分析

wenlong201807 commented 2 years ago

代码块


var solveNQueens = function (n) {
  function isValid(row, col, chessBoard, n) {
    for (let i = 0; i < row; i++) {
      if (chessBoard[i][col] === 'Q') {
        return false;
      }
    }

    for (let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
      if (chessBoard[i][j] === 'Q') {
        return false;
      }
    }

    for (let i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
      if (chessBoard[i][j] === 'Q') {
        return false;
      }
    }
    return true;
  }

  function transformChessBoard(chessBoard) {
    let chessBoardBack = [];
    chessBoard.forEach((row) => {
      let rowStr = '';
      row.forEach((value) => {
        rowStr += value;
      });
      chessBoardBack.push(rowStr);
    });

    return chessBoardBack;
  }

  let result = [];
  function backtracing(row, chessBoard) {
    if (row === n) {
      result.push(transformChessBoard(chessBoard));
      return;
    }
    for (let col = 0; col < n; col++) {
      if (isValid(row, col, chessBoard, n)) {
        chessBoard[row][col] = 'Q';
        backtracing(row + 1, chessBoard);
        chessBoard[row][col] = '.';
      }
    }
  }
  let chessBoard = new Array(n).fill([]).map(() => new Array(n).fill('.'));
  backtracing(0, chessBoard);
  return result;
};

时间复杂度和空间复杂度

Moin-Jer commented 2 years ago

思路


回溯

代码


class Solution {
    int ans = 0;
    public int totalNQueens(int n) {
        Set<Integer> col = new HashSet<>();
        Set<Integer> r = new HashSet<>();
        Set<Integer> l = new HashSet<>();
        backtrack(n, 0, col, r, l);
        return ans;
    }

    private void backtrack(int n, int row, Set<Integer> col, Set<Integer> r, Set<Integer> l) {
        if (row == n) {
            ++ans;
            return;
        }
        for (int i = 0; i < n; ++i) {
            if (col.contains(i)) {
                continue;
            }
            if (r.contains(row - i)) {
                continue;
            }
            if (l.contains(row + i)) {
                continue;
            }
            col.add(i);
            r.add(row - i);
            l.add(row + i);
            backtrack(n, row + 1, col, r, l);
            col.remove(i);
            r.remove(row - i);
            l.remove(row + i);
        }
    }
}

复杂度分析


kbfx1234 commented 2 years ago

52. N皇后 II

//cpp 1-29
class Solution {
public:
    int ret = 0;;

    void backtrack(int n, int row, vector<string>& cb) {
        if (row == n) {
            ret++;
            return;
        }
        for (int col = 0; col < n; col++) {
            if (judge(row, col, cb, n)) {
                cb[row][col] = 'Q';
                backtrack(n, row+1, cb);
                cb[row][col] = '.'; // 回溯

            }
        }
    }
    bool judge (int row, int col, vector<string> & cb, int n) {
        // 每行判断
        for (int i = 0; i < row; i++) {
            if (cb[i][col] == 'Q') {
                return false;
            }
        }
        // 左上角
        for (int i = row-1, j = col-1; i >= 0&&j >= 0; i--, j--) {
            if(cb[i][j] == 'Q') {
                return false;
            }
        }
        // 右上角
        for (int i = row-1, j = col+1; i >= 0&&j < n; i--, j++) {
            if(cb[i][j] == 'Q') {
                return false;
            }

        }
        return true;
    }
    int totalNQueens(int n) {
        vector<string> cb(n, string(n, '.'));
        backtrack(n, 0 , cb);
        return ret;

    }
};
Myleswork commented 2 years ago

思路

n皇后是回溯法非常经典的题了

这题要的是解法数量,如果要解法的话,把count改成string就行,或者一个int数组,只要能存储第i个皇后放置的位置的数据结构都可以

代码

class Solution {
public:
    bool isvalid(vector<vector<bool>>& board,int row,int col,int n){
        for(int i = 0;i<row;i++){
            if(board[i][col]) return false;
        }
        for(int i = row-1;i>=0;i--){
            if(col-row+i<0) break;
            if(board[i][col-row+i]) return false;
        }
        for(int i = row-1;i>=0;i--){
            if(col+row-i>=n) break;
            if(board[i][col+row-i]) return false;
        }
        return true;
    }

    void backtrack(vector<vector<bool>>& board,int row,int n,int& count){
        if(row==n){
            count++;
            return;
        }
        for(int col = 0;col<n;col++){
            if(isvalid(board,row,col,n)){
                board[row][col] = true;
                backtrack(board,row+1,n,count);
                board[row][col] = false;
            }
        }
    }

    int totalNQueens(int n) {
        int count = 0;
        vector<vector<bool>> board(n,vector<bool>(n,false));
        backtrack(board,0,n,count);
        return count;
    }
};

复杂度分析

时间复杂度:O(n!)

空间复杂度:O(n)

jiaqiliu37 commented 2 years ago
class Solution:
    def totalNQueens(self, n: int) -> int:
        ans = 0

        def backtrack(row, diagonals, anti_diagonals, cols):
            nonlocal ans
            if row == n:
                ans += 1
                return
            for col in range(n):
                cur_diagonal = row + col
                cur_anti_diagonal = row - col
                if col in cols or cur_diagonal in diagonals or cur_anti_diagonal in anti_diagonals or col in cols:
                    continue

                diagonals.add(cur_diagonal)
                anti_diagonals.add(cur_anti_diagonal)
                cols.add(col)
                backtrack(row + 1, diagonals, anti_diagonals, cols)
                diagonals.remove(cur_diagonal)
                anti_diagonals.remove(cur_anti_diagonal)
                cols.remove(col)

        backtrack(0, set(), set(), set())
        return ans

Time complexity O(n!) Space complexity O(n)

zol013 commented 2 years ago
class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:

        def create_board(state):
            board = []
            for row in state:
                board.append(''.join(row))

            return board

        def backtrack(row, cols, diagonals, anti_diagonals, state):
            if row == n:
                ans.append(create_board(state))
                return

            for col in range(n):
                d = row - col
                anti_d = row + col

                if col in cols or d in diagonals or anti_d in anti_diagonals:
                    continue

                state[row][col] = 'Q'
                diagonals.add(d)
                anti_diagonals.add(anti_d)
                cols.add(col)
                backtrack(row + 1, cols, diagonals, anti_diagonals,state)

                state[row][col] = '.'
                diagonals.remove(d)
                anti_diagonals.remove(anti_d)
                cols.remove(col)

        empty_board = [['.'] * n for _ in range(n)]
        ans = []
        backtrack(0, set(), set(), set(), empty_board)
        return ans
falconruo commented 2 years ago

思路:

回溯法(Backtracking)

复杂度分析:

方法一、 class Solution { public: int totalNQueens(int n) { set rows; set d1; set d2;

    return backTracking(n, 0, rows, d1, d2);
}

private: int backTracking(int n, int col, set& rows, set& d1, set& d2) { if (col == n) return 1;

    int res = 0;

    for (int i = 0; i < n; ++i) {
        if (rows.count(i) || d1.count(col - i) || d2.count(col + i)) continue;

        rows.insert(i);
        d1.insert(col - i);
        d2.insert(col + i);
        res += backTrack(n, col + 1, rows, d1, d2);
        rows.erase(i);
        d1.erase(col - i);
        d2.erase(col + i);
    }

    return res;
}

};

wxj783428795 commented 2 years ago

思路

好难,先抄作业

const totalNQueens = function (n) {
  let res = 0;
  const dfs = (n, row, col, pie, na) => {
    if (row >= n) {
      res++;
      return;
    }
    // 将所有能放置 Q 的位置由 0 变成 1,以便进行后续的位遍历
    // 也就是得到当前所有的空位
    let bits = ~(col | pie | na) & ((1 << n) - 1);
    while (bits) {
      // 取最低位的1
      let p = bits & -bits;
      // 把P位置上放入皇后
      bits = bits & (bits - 1);
      // row + 1 搜索下一行可能的位置
      // col | p 目前所有放置皇后的列
      // (pie | p) << 1 和 (na | p) >> 1) 与已放置过皇后的位置 位于一条斜线上的位置
      dfs(n, row + 1, col | p, (pie | p) << 1, (na | p) >> 1);
    }
  };
  dfs(n, 0, 0, 0, 0);
  return res;
};
1149004121 commented 2 years ago
  1. N皇后 II

思路

皇后的同一行、同一列、左右方向的斜线上都不能有皇后,考虑用位运算分别表示已经占据的列、左斜线、右斜线的信息,1表示已经占据,0表示可以使用。

代码

var totalNQueens = function (n) {
  let res = 0;
  dfs(n, 0, 0, 0, 0);
  return res;

  function dfs(n, row, cols, diag1, diag2) {
    if (n === row) res++;
    // 此时1表明下一轮可取的范围
    let bits = (~(cols | diag1 | diag2)) & ((1 << n) - 1);
    while (bits) {
      // 取最右一位1
      let p = bits & (-bits);
      // 最右1位1归0
      bits = bits & (bits - 1);
      // <<表示向左下方 >>表示向右下方移动
      dfs(n, row + 1, (cols | p), (diag1 | p) << 1, (diag2 | p) >> 1);
    }
  }
};

复杂度分析

junbuer commented 2 years ago

思路

代码

class Solution(object):
    def totalNQueens(self, n):
        """
        :type n: int
        :rtype: int
        """
        def backtrack(row):
            if row == n:
                return 1
            else:
                count = 0

            for i in range(n):

                if i in cols or row - i in dia1 or row + i in dia2:
                    continue

                cols.add(i)
                dia1.add(row - i)
                dia2.add(row + i)

                count += backtrack(row + 1)

                cols.remove(i)
                dia1.remove(row - i)
                dia2.remove(row + i)
            return count

        cols, dia1, dia2 = set(), set(), set()
        return backtrack(0)

复杂度分析

stackvoid commented 2 years ago

思路

不会。。。看答案 回溯?

代码

class Solution {
    public int totalNQueens(int n) {
        Set<Integer> columns = new HashSet<Integer>();
        Set<Integer> diagonals1 = new HashSet<Integer>();
        Set<Integer> diagonals2 = new HashSet<Integer>();
        return backtrack(n, 0, columns, diagonals1, diagonals2);
    }

    public int backtrack(int n, int row, Set<Integer> columns, Set<Integer> diagonals1, Set<Integer> diagonals2) {
        if (row == n) {
            return 1;
        } else {
            int count = 0;
            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;
                }
                columns.add(i);
                diagonals1.add(diagonal1);
                diagonals2.add(diagonal2);
                count += backtrack(n, row + 1, columns, diagonals1, diagonals2);
                columns.remove(i);
                diagonals1.remove(diagonal1);
                diagonals2.remove(diagonal2);
            }
            return count;
        }
    }
}

算法分析

Time O(N) Space O(N)

callmeerika commented 2 years ago

思路

回溯

代码

var deal = (n, row, col, arr1, arr2) => {
    if (row === n) return 1;
    let count = 0;
    for (let i = 0; i < n; i++) {
        if (col.has(i)) continue;
        if (arr1.has(row - i)) continue;
        if (arr2.has(row + i)) continue;
        col.add(i);
        arr1.add(row - i);
        arr2.add(row + i);
        count += deal(n, row + 1, col, arr1, arr2);
        col.delete(i);
        arr1.delete(row - i);
        arr2.delete(row + i);
    }
    return count;
}
var totalNQueens = function(n) {
    const col = new Set();
    const arr1 = new Set();
    const arr2 = new Set();
    return deal(n, 0, col, arr1, arr2);
};

复杂度

时间复杂度:O(n!)
空间复杂度:O(n)

Aobasyp commented 2 years ago

思路 DFS(深度优先搜索)

const totalNQueens = function (n) { let res = 0; const dfs = (n, row, col, pie, na) => { if (row >= n) { res++; return; } // 将所有能放置 Q 的位置由 0 变成 1,以便进行后续的位遍历 // 也就是得到当前所有的空位 let bits = ~(col | pie | na) & ((1 << n) - 1); while (bits) { // 取最低位的1 let p = bits & -bits; // 把P位置上放入皇后 bits = bits & (bits - 1); // row + 1 搜索下一行可能的位置 // col | p 目前所有放置皇后的列 // (pie | p) << 1 和 (na | p) >> 1) 与已放置过皇后的位置 位于一条斜线上的位置 dfs(n, row + 1, col | p, (pie | p) << 1, (na | p) >> 1); } }; dfs(n, 0, 0, 0, 0); return res; };

时间复杂度为 O(n!) 空间复杂度为 O(n)

Toms-BigData commented 2 years ago

【Day 49】52. N 皇后 II

思路

回溯算法,通过公式将每一个皇后的位置摆放好,不断计数,达到n的话表明该方法成立 ans+1

golang代码

func totalNQueens(n int) (ans int) {
    columns := make([]bool, n)
    diagonals1 := make([]bool, 2*n-1)
    diagonals2 := make([]bool, 2*n-1)
    var backtrack func(int)
    backtrack = func(row int) {
        if row == n{
            ans++
            return
        }
        for col, hasQueen := range columns{
            d1, d2 :=row+n-1-col, row+col
            if hasQueen || diagonals1[d1] || diagonals2[d2]{
                continue
            }
            columns[col] = true
            diagonals1[d1] = true
            diagonals2[d2] = true
            backtrack(row+1)
            columns[col] = false
        }
    }
    backtrack(0)
    return
}

复杂度

时间:O(n!) 空间:O(n)

alongchong commented 2 years ago
class Solution {
    public int totalNQueens(int n) {
        Set<Integer> columns = new HashSet<Integer>();
        Set<Integer> diagonals1 = new HashSet<Integer>();
        Set<Integer> diagonals2 = new HashSet<Integer>();
        return backtrack(n, 0, columns, diagonals1, diagonals2);
    }

    public int backtrack(int n, int row, Set<Integer> columns, Set<Integer> diagonals1, Set<Integer> diagonals2) {
        if (row == n) {
            return 1;
        } else {
            int count = 0;
            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;
                }
                columns.add(i);
                diagonals1.add(diagonal1);
                diagonals2.add(diagonal2);
                count += backtrack(n, row + 1, columns, diagonals1, diagonals2);
                columns.remove(i);
                diagonals1.remove(diagonal1);
                diagonals2.remove(diagonal2);
            }
            return count;
        }
    }
}
charlestang commented 2 years ago

思路

回溯法

  1. 关键怎么记录每一种答案,可以用一个 长度 n 的列表,第 i 个数字代表第 i 行皇后的座标;
  2. 怎么检查位置是否可以摆放。假如,我们在第 i 行,j 列尝试放一个皇后,那么在所有的 x 行,x < i,p[x] != j 代表同一列不能再次放置。p[x] != j - i +x && p[x] != j + i - x 代表对角线冲突。

时间复杂度 O(n!) 空间复杂度 O(n)

代码

class Solution:
    def totalNQueens(self, n: int) -> int:
        p = [-1] * n

        def check(i: int, j: int) -> bool:
            for x in range(i):
                if p[x] == j: return False
                if p[x] == j + i - x or p[x] == j - i + x: return False
            return True

        ans = 0
        def dfs(i: int):
            if i == n:
                nonlocal ans
                ans += 1
            else:
                for j in range(n):
                    if check(i, j):
                        p[i] = j
                        dfs(i + 1)
                        p[i] = -1

        dfs(0)
        return ans
dahaiyidi commented 2 years ago

Problem

52. N皇后 II

++

n 皇后问题 研究的是如何将 n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。


Note


Complexity


Python

C++

class Solution {
public:
    int totalNQueens(int n) {
        dfs(n, 0, 0, 0, 0);
        return res;

    }

    void dfs(int n, int row, int col, int ld, int rd){
        if(row >= n){
            res++;
            return;
        }
        int bits = ~(col | ld | rd) & ((1 << n) - 1); // bits 代表了当前行可放置的col, ((1 << n) - 1) 代表设置了n个1,col | ld | rd分别代表由于同一列,左斜,右斜而无法使用的列
        while(bits > 0){
            int pick = bits & (-bits); // 提取bits的最后一个1
            dfs(n, row + 1, col | pick, (ld | pick) << 1, (rd | pick) >> 1);
            bits = bits & bits - 1; // bits的最后一个1替换为0
        }
    }
private:
    int res = 0;
};

From : https://github.com/dahaiyidi/awsome-leetcode

declan92 commented 2 years ago

思路

  1. 将皇后按行序放置;
  2. 前面放置的皇后位置会影响后面皇后放置位置,需要记录皇后放置的位置;
  3. 判断能够满足放置,则放皇后,当row==n时,表示成功放置所有皇后;
  4. 递归向上冒泡时,需要清空记录位置,决策树走入下一个分支时,正确判断满足放置条件; 细节
  5. 如何记录皇后放置位置
  6. 如何判断该位置皇后能否放置 使用三个集合记录和判断
    columns:已放置皇后的列号加入集合
    diagonals1:row+column已经放置皇后加入集合;
    diagonals2:row-column已经皇后加入集合;
    三个集合都不包含该位置,则该位置可以放置
    java code
    class Solution {
    public int totalNQueens(int n) {
        Set<Integer> columns = new HashSet();
        Set<Integer> diagonals1 = new HashSet();
        Set<Integer> diagonals2 = new HashSet();
        return backtrack(n,0,columns,diagonals1,diagonals2);
    }
    public int backtrack(int n,int row,Set<Integer> columns,Set<Integer> diagonals1,Set<Integer> diagonals2 ){
        if(row == n){
            return 1;
        }
        int count = 0;
        for(int i = 0;i<n;i++){
            if(columns.contains(i)){
                continue;
            }
            if(diagonals1.contains(row+i)){
                continue;
            }
            if(diagonals2.contains(row-i)){
                continue;
            }
            count+=backtrack(n,row+1,columns,diagonals1,diagonals2);
            columns.remove(i);
            diagonals1.remove(row+i);
            diagonals2.remove(row-i);
        }
        return count;
    }
    }

    时间:O(n!),回溯
    空间:O(n),调用栈不超过n,集合长度不会超过n

Richard-LYF commented 2 years ago

class Solution: def totalNQueens(self, n: int) -> int: def backtrack(row: int) -> int: if row == n: return 1 else: count = 0 for i in range(n): if i in columns or row - i in diagonal1 or row + i in diagonal2: continue columns.add(i) diagonal1.add(row - i) diagonal2.add(row + i) count += backtrack(row + 1) columns.remove(i) diagonal1.remove(row - i) diagonal2.remove(row + i) return count

    columns = set()
    diagonal1 = set()
    diagonal2 = set()
    return backtrack(0)
WANGDI-1291 commented 2 years ago

代码

/**
 * @param {number} n
 * @return {number}
 * @param row 当前层
 * @param col 列
 * @param pie 左斜线
 * @param na 右斜线
 */
const totalNQueens = function (n) {
  let res = 0;
  const dfs = (n, row, col, pie, na) => {
    if (row >= n) {
      res++;
      return;
    }
    // 将所有能放置 Q 的位置由 0 变成 1,以便进行后续的位遍历
    // 也就是得到当前所有的空位
    let bits = ~(col | pie | na) & ((1 << n) - 1);
    while (bits) {
      // 取最低位的1
      let p = bits & -bits;
      // 把P位置上放入皇后
      bits = bits & (bits - 1);
      // row + 1 搜索下一行可能的位置
      // col | p 目前所有放置皇后的列
      // (pie | p) << 1 和 (na | p) >> 1) 与已放置过皇后的位置 位于一条斜线上的位置
      dfs(n, row + 1, col | p, (pie | p) << 1, (na | p) >> 1);
    }
  };
  dfs(n, 0, 0, 0, 0);
  return res;
};
last-Battle commented 2 years ago
class Solution {
public:
    int totalNQueens(int n) {

        vector<int> onePath;
        int ret=0; 

        backTrac(n, onePath, 0, ret); 
        return ret; 

    }

    void backTrac(int n, vector<int>& onePath, int row,  int& ret)
    {
        if(onePath.size()==n)  
        {
            ret++; 
            return;             
        }            
        for(int col =0; col <n; col++) 
        {
            if(isValid(onePath, row, col))
            {
                onePath.push_back(col); 
                backTrac(n, onePath, row+1, ret);
                onePath.pop_back(); 
            }
        }
    }

    bool isValid(vector<int>& onePath, int irow, int icol)
    {
        for(int i=0; i< onePath.size(); i++)
        {
            if(onePath[i] == icol)
                return false; 
            if(onePath[i]+(irow-i) == icol)
                return false; 
            if(onePath[i]-(irow-i) == icol)
                return false; 
        }        
        return true;         
    }
};
fornobugworld commented 2 years ago

答案虽然不长,但是。。 class Solution: def totalNQueens(self, n: int) -> int: def solve(row: int, columns: int, diagonals1: int, diagonals2: int) -> int: if row == n: return 1 else: count = 0 availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2)) while availablePositions: position = availablePositions & (-availablePositions) availablePositions = availablePositions & (availablePositions - 1) count += solve(row + 1, columns | position, (diagonals1 | position) << 1, (diagonals2 | position) >> 1) return count

    return solve(0, 0, 0, 0)