LeetCode 51. N-Queens和52. N-Queens II的位運算解法
阿新 • • 發佈:2019-01-22
最近在刷Leetcode,遇到了N皇后的問題。去網上搜了下,發現了一個用位運算求解可行解個數的非常簡單的方法(點選這裡檢視)。博主在裡面添加了非常詳細的註釋和解釋,只要仔細研究一下,相信每個人都能看懂。
LeetCode 52題只要求輸出可行解的個數,用上面博主的程式碼便可輕鬆通過。52題的AC程式碼如下:(註釋已刪除,可檢視上面博主的註釋)
class Solution { public: int totalNQueens(int n) { limit = (1 << n) - 1; return nQueens(0, 0, 0); } private: int nQueens(int res, int ld, int rd) { if (res != limit) { int pos = limit & ~(res | ld | rd); int result = 0; while (pos) { int p = pos & -pos; pos -= p; result += nQueens(res + p, (ld + p) << 1, (rd + p) >> 1); } return result; } return 1; } int limit; };
但是51題需要求出所有的可行解,看了很多部落格好像都是用普通的列舉+約束來做的(這篇部落格的約束函式寫得非常簡單易懂,可以看一下),但是沒有看到用位運算來解決的。於是嘗試著改了一下上面的程式碼,發現只需要做很小的變動就可以了。51題的AC程式碼如下:
class Solution { public: vector<vector<string>> solveNQueens(int n) { limit = (1 << n) - 1; vector<string> vec(n, string(n, '.'));// 初始化一個全是'.'的vector,用來儲存嘗試結果 nQueue(0, 0, 0, 0, vec);// 引數k初始化為0,表示第0行 return result; } private: // 第4個引數k表示嘗試的行數 void nQueue(long res, long ld, long rd, int k, vector<string>& vec) { if (res != limit) { int pos = limit & ~(res | ld | rd); while (pos) { int p = pos & -pos; pos -= p; /** * pos = 2^t0 + 2^t1 + 2^t2 + ... (t0 < t1 < t2 < ...) * 則p = 2^t0,log2(p) = t0 * t0則為可放置皇后的列 */ vec[k][log2(p)] = 'Q';// 在第k行第t0列嘗試放置一個皇后 nQueue(res + p, (ld + p) << 1, (rd + p) >> 1, k + 1, vec);// k + 1 : 繼續進行下一行的嘗試 vec[k][log2(p)] = '.';// 因為引數是引用,所以此處要復原vec } } else result.push_back(vec);// 找到一個解,新增到結果中 } vector<vector<string>> result; int limit; };
位運算的程式碼提交後,Run Time只用了3ms,試了下其他的方法,都在15ms左右,速度確實提高了很多。如果大家有更好的方法,歡迎交流~