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

又是一道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();
            }

        }
    }

};

另外,这题还可以优化。主要是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,这样就没有负数了。

你可能感兴趣的:(LintCode-33: N-Queens (DFS排列经典题!))