N-Queens I & II (Leetcode 51, 52)

著名的“N皇后”問題。主要思路是:我們逐行進行DFS,而在每一行的DFS中逐列掃描,放置皇后。

N Queens I: https://leetcode.com/problems/n-queens/description/
N Queens II: https://leetcode.com/problems/n-queens-ii/description/

而判斷皇后位置是否合適,則需要一個prevoius position函數。previous[i] = c, means one Queen is on row i, col c。
由于我們逐行DFS,則保證了行不一樣。列,和對角線的check利用如下函數,需要遍歷所有之前放置的位置。其中對角線的check非常巧妙。

 bool isValid(int row, int col, vector<int> &pos){
        for(int i=0; i<pos.size(); i++){
            if(col == pos[i] || (abs(i-row) == abs(pos[i] - col))) return false;
        }
        return true;
    }

N-Queens I:

class Solution {
public:
    
    bool isValid(int row, int col_idx, vector<int> &record){
        for(int i=0; i<record.size(); i++){
            if(record[i] == col_idx || row - i == abs(col_idx - record[i])) return false;
        }
        return true;
    }
    
    void findcombo(vector<vector<string>> &allcomb, vector<int> &record, int row, int n){
        if(row == n){
            vector<string> comb;
            for(int i=0; i<record.size(); i++){
                int idx = record[i];
                string temp = string(n, '.');
                temp[idx] = 'Q';
                comb.push_back(temp);
            }
            allcomb.push_back(comb);
            return;
        }
        for(int i=0; i<n; i++){
            if(!isValid(row, i, record)) continue;
            record.push_back(i);
            findcombo(allcomb, record, row+1, n);
            record.pop_back();
        }
    }

    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> allcomb;
        if(n <= 0) return allcomb;
        vector<int> record;
        findcombo(allcomb, record, 0, n);
        return allcomb;
    }
};

II 和 I 的做法基本一樣,也是用DFS來做。用一個cnt變量,來記錄滿足條件個數。

class Solution {
public:
    int totalNQueens(int n) {
        if(n <= 0) return 0;
        int cnt = 0;
        vector<int> pos;
        findcombo(cnt, pos, 0, n);
        return cnt;
    }
    
    void findcombo(int &cnt, vector<int> &pos, int cur, int n){
        if(cur == n){
            cnt++;
        }
        for(int i=0; i<n; i++){
            if(isValid(cur, i, pos)){
                pos.push_back(i);
                findcombo(cnt, pos, cur+1, n);
                pos.pop_back();
            }
        }
    }
    
    bool isValid(int row, int col, vector<int> &pos){
        for(int i=0; i<pos.size(); i++){
            if(col == pos[i] || (abs(row-i) == abs(col-pos[i]))) return false;
        }
        return true;
    }
};
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 回溯算法 回溯法:也稱為試探法,它并不考慮問題規模的大小,而是從問題的最明顯的最小規模開始逐步求解出可能的答案,并...
    fredal閱讀 13,728評論 0 89
  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經驗。 張土汪:刷leetcod...
    土汪閱讀 12,769評論 0 33
  • 原題 n皇后問題是將n個皇后放置在n*n的棋盤上,皇后彼此之間不能相互攻擊。給定一個整數n,返回所有不同的n皇后問...
    Jason_Yuan閱讀 2,106評論 0 0
  • 如果面試碰到這么難的題..感覺可以掛電話了。 這題看到首先第一個可以確定的是這個肯定會用到DFS backtrac...
    98Future閱讀 243評論 0 0
  • 最好的狀態就是專注而富有效率的工作一整天。不要太晚下班,有一兩個疑問路上左思右想,最終想明白,恍然大悟,開心的不得...
    關山之矛閱讀 489評論 0 0