题目描述(困难难度)

52. N-Queens II - 图1

上一题一样,只不过这次不需要返回所有结果,只需要返回有多少个解就可以。

解法一

我们直接把上道题的 ans 的 size 返回就可以了,此外 currentQueen.size ( ) == n 的时候,也不用去生成一个解了,直接加一个数字占位。

  1. public int totalNQueens(int n) {
  2. List<Integer> ans = new ArrayList<>();
  3. backtrack(new ArrayList<Integer>(), ans, n);
  4. return ans.size();
  5. }
  6. private void backtrack(List<Integer> currentQueen, List<Integer> ans, int n) {
  7. if (currentQueen.size() == n) {
  8. ans.add(1);
  9. return;
  10. }
  11. for (int col = 0; col < n; col++) {
  12. if (!currentQueen.contains(col)) {
  13. if (isDiagonalAttack(currentQueen, col)) {
  14. continue;
  15. }
  16. currentQueen.add(col);
  17. backtrack(currentQueen, ans, n);
  18. currentQueen.remove(currentQueen.size() - 1);
  19. }
  20. }
  21. }
  22. private boolean isDiagonalAttack(List<Integer> currentQueen, int i) {
  23. int current_row = currentQueen.size();
  24. int current_col = i;
  25. for (int row = 0; row < currentQueen.size(); row++) {
  26. if (Math.abs(current_row - row) == Math.abs(current_col - currentQueen.get(row))) {
  27. return true;
  28. }
  29. }
  30. return false;
  31. }

时间复杂度:

空间复杂度:

解法二

参考这里)。

既然不用返回所有解,那么我们就不需要 currentQueen 来保存当前已加入皇后的位置。只需要一个 bool 型数组,来标记列是否被占有就可以了。

由于没有了 currentQueen,所有不能再用之前 isDiagonalAttack 判断对角线冲突的方法了。我们可以观察下,对角线元素的情况。

52. N-Queens II - 图2

可以发现对于同一条副对角线,row + col 的值是相等的。

对于同一条主对角线,row - col 的值是相等的。

我们同样可以用一个 bool 型数组,来保存当前对角线是否有元素,把它们相加相减的值作为下标。

对于 row - col ,由于出现了负数,所以可以加 1 个 n,由 [ - 3, 3 ] 转换为 [ 1 , 7 ] 。

  1. public int totalNQueens(int n) {
  2. List<Integer> ans = new ArrayList<>();
  3. boolean[] cols = new boolean[n]; // 列
  4. boolean[] d1 = new boolean[2 * n]; // 主对角线
  5. boolean[] d2 = new boolean[2 * n]; // 副对角线
  6. return backtrack(0, cols, d1, d2, n, 0);
  7. }
  8. private int backtrack(int row, boolean[] cols, boolean[] d1, boolean[] d2, int n, int count) {
  9. if (row == n) {
  10. count++;
  11. } else {
  12. for (int col = 0; col < n; col++) {
  13. int id1 = row - col + n; //主对角线加 n
  14. int id2 = row + col;
  15. if (cols[col] || d1[id1] || d2[id2])
  16. continue;
  17. cols[col] = true;
  18. d1[id1] = true;
  19. d2[id2] = true;
  20. count = backtrack(row + 1, cols, d1, d2, n, count);
  21. cols[col] = false;
  22. d1[id1] = false;
  23. d2[id2] = false;
  24. }
  25. }
  26. return count;
  27. }

时间复杂度:

空间复杂度:

和上一题相比,通过三个 bool 型数组来标记是否占有,不存储具体的位置,从而解决了这道题。

windliang wechat

添加好友一起进步~

如果觉得有帮助的话,可以点击 这里 给一个 star 哦 ^^

如果想系统的学习数据结构和算法,强烈推荐一个我之前学过的课程,可以点击 这里 查看详情