N 皇后问题 DFS + 位运算优化

52. N皇后 II

x 轴 在右边、 y 轴在下边

因为是一行一行遍历, 所以不需要 rows[] 这样的行 只需要维护一个 cols 的列

pie y = -x => x + y = c

na y = x => x - y = c

var totalNQueens = function(n) {
  let res = 0
  const cols = new Set()
  const pie = new Set()		// x + y
  const na = new Set()		// x - y
  const dfs = (n, row) => {
    if (row == n) {
      res++
      return
    }
    for (let col = 0; col < n; col++) {
      if (cols.has(col) || pie.has(row + col) || na.has(row - col)) continue
      
      cols.add(col)
      pie.add(row + col)
      na.add(row - col)

      dfs(n, row + 1)

      cols.delete(col)
      pie.delete(row + col)
      na.delete(row - col)
    }
  }
  dfs(n, 0)
  return res
};

基于位运算的回溯

一开始 如 col 为 1010 表示 第一位和第三位已经放置元素了 并且与 pie | na 或之后 取反 表示第二位和第四位可以放元素 可是这时候前面有许多的1 如 11110101 这时需去除

(1 << n) - 1 00001111 只留下最后四位

var totalNQueens = function(n) {
  let res = 0
  const dfs = (row, col, pie, na) => {
    if (row == n) {
      res++
      return
    }

    // 得到可以放位置的 bits
    let bits = (~(col | pie | na)) & ((1 << n) - 1)
    while (bits) {
      // 得到最后的 1 的位置
      const p = bits & -bits
      // col | p 更新列,表示这个列已经占据一个皇后。向下走一行后,撇捺要往左右移动一位
      dfs(row + 1, col | p, (pie | p) << 1, (na | p) >> 1)
      // 去掉最后的 1
      bits &= bits - 1
    }
    
  }
  dfs(0, 0, 0, 0)		
  return res
};
51. N 皇后
var solveNQueens = function (n) {
  const res = []
  const cols = new Set()
  const pie = new Set()		// x + y
  const na = new Set()		// x - y
  
  const dfs = (n, row, cur_state) => {
    if (row == n) {
      res.push(cur_state)
      return
    }
    for (let col = 0; col < n; col++) {
      if (cols.has(col) || pie.has(row + col) || na.has(row - col)) continue
      
      cols.add(col)
      pie.add(row + col)
      na.add(row - col)
      
      dfs(n, row + 1, cur_state + col)

      cols.delete(col)
      pie.delete(row + col)
      na.delete(row - col)
    }
  }
  
  dfs(n, 0, [])		
  
  const _generate_result = (n) => {
    const borads = []
    for (const r of res) {
      const borad = []
      for (const i of r) {		
        borad.push(".".repeat(i) + "Q" + ".".repeat(n - i - 1))
      }
      borads.push(borad)
    }
    return borads
  }
  return _generate_result(n)
};

基于位运算的回溯

var solveNQueens = function (n) {
  const res = new Set()
  const dfs = (row, col, pie, na, cur_state) => {
    if (row == n) {
      res.add(cur_state)
      return
    }
    // 得到可以放皇后的位置(0 表示没有皇后放置),取反为 1 表示可以放置皇后 &去掉前面冗余的数字
    let bits = (~(col | pie | na)) & ((1 << n) - 1)
    while (bits) {
      // 得到最后的 1 的位置
      const p = bits & -bits
      // log2^n  = Math.log(n) / Math.log(2)		得到具体的位数
      const Qcol = Math.log((col | p) - col) / Math.log(2)
      dfs(row + 1, col | p, (pie | p) << 1, (na | p) >> 1, cur_state + Qcol)
      // 去掉最后的 1
      bits &= bits - 1
    }

  }
  dfs(0, 0, 0, 0, [])

  const _generate_result = (n) => {
    const borads = []
    for (const r of res) {
      const borad = []
      for (const i of r) {
        borad.push(".".repeat(n - i - 1) + "Q" + ".".repeat(i))
      }
      borads.push(borad)
    }
    return borads
  }
  return _generate_result(n)
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值