LintCode-33: N-Queens (DFS排列经典题!)

本文介绍了一种使用深度优先搜索(DFS)解决N皇后问题的方法,并详细解释了如何通过一个isValid()函数来检查列冲突及对角线冲突,确保放置的皇后不会互相攻击。此外还提供了一种优化方案,利用三个数组跟踪列、对角线和反对角线的状态,以降低检查冲突的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

又是一道DFS排列经典题。这题用visited[]还不够,要专门用一个isValid()函数来确保没有列冲突和两个对角线冲突。

注意:
1) string的初始化:
string dotStr(n, ‘.’);
vector solString(n, dotStr); //good string initialization code!

代码如下:

class Solution {
public:
    /*
     * @param n: The number of queens
     * @return: All distinct solutions
     */
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> results;
        vector<int> sol;
        if (n == 0) {
            results.push_back(vector<string>());
            return results;
        }
        
        helper(n, 0, sol, results);
        return results;
    }
    
private:
    bool isValid(vector<int> &sol, int col) {
        int row = sol.size();
        for (int rowId = 0; rowId < sol.size(); ++rowId) {
            if (sol[rowId] == col) 
                return false;
            if (sol[rowId] + rowId == col + row)
                return false;
            if (sol[rowId] - rowId == col - row)
                return false;
        }
        return true;
    }
    
    void helper(int n, int index, vector<int>&sol, vector<vector<string>> &results) {
        if (index == n) {
            string dotStr(n, '.');
            vector<string> solString(n, dotStr);   //good string initialization code!
            for (auto i : sol) {
                solString[i][sol[i]] = 'Q';
            }
            results.push_back(solString);
            return;
        }
        
        for (int i = 0; i < n; ++i) {
            
            if (isValid(sol, i)) {
                sol.push_back(i);
                helper(n, index + 1, sol, results);
                sol.pop_back();
            }
            
        }
    }
    
};

写成下面这样也可以。这样for loop里面用sol[index] = i; 就可以了,不用push_back又pop_back。

class Solution {
public:
    /*
     * @param n: The number of queens
     * @return: All distinct solutions
     */
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> results;
        vector<int> sol(n, 0);
        if (n == 0) {
            results.push_back(vector<string>());
            return results;
        }

        helper(n, 0, sol, results);
        return results;
    }

private:
    bool isValid(vector<int> &sol, int col, int index) {
        int row = index; //sol.size();
        for (int rowId = 0; rowId < index; ++rowId) {
            if (sol[rowId] == col) 
                return false;
            if (sol[rowId] + rowId == col + row)
                return false;
            if (sol[rowId] - rowId == col - row)
                return false;
        }
        return true;
    }

    void helper(int n, int index, vector<int>&sol, vector<vector<string>> &results) {
        if (index == n) {
            string dotStr(n, '.');
            vector<string> solString(n, dotStr);   //good string initialization code!
            for (auto i : sol) {
                solString[i][sol[i]] = 'Q';
            }
            results.push_back(solString);
            return;
        }

        for (int i = 0; i < n; ++i) {

            if (isValid(sol, i, index)) {
                sol[index] = i;
                helper(n, index + 1, sol, results);
            }

        }
    }
};

另外,这题还可以优化。主要是isValid()的复杂度可以从O(n)降到O(1)。我们可以设3个长度为n…2n的数组,分别表示列,对角线和反对角线是否有冲突。反对角线可以用i+j,即如果i行j列有Queen,则a[i+j]=1。对角线则要用i-j或j-i。但这里有个问题因为i-j或j-i可能为负。一个技巧就是用i-j+n,这样就没有负数了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值