【一天一大 lee】N皇后 II (難度:困難) - Day20201017

坑人的小書童發表於2020-10-17

20201017

題目:

n 皇后問題研究的是如何將 n 個皇后放置在 n×n 的棋盤上,並且使皇后彼此之間不能相互攻擊。

N 皇后 II

給定一個整數 n,返回 n 皇后不同的解決方案的數量。

示例:

輸入: 4
輸出: 2
解釋: 4 皇后問題存在如下兩個不同的解法。
[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

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

提示:

  • 皇后,是國際象棋中的棋子,意味著國王的妻子。皇后只做一件事,那就是“吃子”。當她遇見可以吃的棋子時,就迅速衝上去吃掉棋子。當然,她橫、豎、斜都可走一或 N-1 步,可進可退。(引用自 百度百科 - 皇后 )

拋磚引玉

類似的題目之前做過N 皇后,兩題的邏輯一致,只是返回值要求不同,本題只要求返回結果數量

遞迴回溯

  1. 從第一行放置 N,之後按照要求(同一條橫行、縱行或斜線上)逐個放置之後的 N
  2. 如果能放置完成 n 個 N 則解法+1
  3. 如果不能放置 n 個則逐個向前回溯更新之前 N 放置的位置

拋磚引玉

/**
 * @param {number} n
 * @return {number}
 */
var totalNQueens = function(n) {
  let _result = 0,
    tmp = []

  dfs(tmp)

  function dfs(tmp) {
    if (tmp.length === n) {
      _result++
      return
    }

    for (let i = 0; i < n; i++) {
      if (isValid(tmp, i)) {
        // 遇到滿足“不能相互攻擊”的點就先佔著後繼續安放下一個Q
        tmp.push(i)
        dfs(tmp)
        // 回溯已經安放的Q
        tmp.pop()
      }
    }
  }

  // 判斷新的位置是否滿足“不能相互攻擊”
  function isValid(tmp, Ny) {
    // 傳入校驗的座標:[Nx,Ny]
    let Nx = tmp.length
    for (let x = 0; x < Nx; x++) {
      let y = tmp[x]
      // 不同列,因為所有做行一定不同行,不在斜對角上[注:斜對角判斷]
      if (y === Ny || Nx - y === x - Ny || Nx + y === x + Ny) {
        return false
      }
    }
    return true
  }

  return _result
}

部落格: 前端小書童

每天的每日一題,寫的題解會同步更新到公眾號一天一大 lee 欄目
歡迎關注留言

公眾號:前端小書童

相關文章