在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

[LintCode/LeetCode] N-Queens I & II [N皇后]

2016-8-16 12:47| 发布者: zhangjf| 查看: 564| 评论: 0

摘要: N-Queens Problem The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all distinct solutions to the n-quee ...
N-Queens Problem

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

Example

There exist two distinct solutions to the 4-queens puzzle:

  1. [
  2. // Solution 1
  3. [".Q..",
  4. "...Q",
  5. "Q...",
  6. "..Q."
  7. ],
  8. // Solution 2
  9. ["..Q.",
  10. "Q...",
  11. "...Q",
  12. ".Q.."
  13. ]
  14. ]
复制代码
Challenge

Can you do it without recursion?

Note

虽然Challenge要求不用recursion,但是我呢比较没出息,就写一种常规方法好了:

首先对于放皇后的流程有一个概念:

结果数组res的形式:包含所有满足条件的,长度为n(row行)的字符串数组cur;每个字符串代表一行的皇后摆法;

首先,在主函数中向结果数组res的一个子集cur,并初始化这个cur中所有元素为长度为n且所有字符都是'.'的字符串;然后调用helper函数;

在helper函数中,结果数组res,目标行数n,和基本子集cur都是确定的,唯一的变量是会被递归的当前行数row,我们会从基本子集cur中取出这一行进行修改:遍历这一行的每个元素,即遍历列数j,然后在第row行第j列的这个元素为'Q'时满足N皇后条件isValid(n, cur, row, j)的情况下,将这个元素设为'Q'。有点拗口?这样吧,先看看isValid(n, cur, row, col)的意思:

isValid()就是当我们想在第i行j列放上Queen的时候,先遍历上面的i-1行,判断有没有能攻击到当前皇后的皇后。

所以在helper函数中,若之前的行中没有威胁到当前遍历到的第row行第j列这个皇后的其它皇后的话,就更新这一行并存入子集cur,然后递归下一行。递归之后,再将这个皇后换成字符'.',以便在下一个循环中将第j+1个字符设为皇后并递归。

当helper函数第n-1次递归的时候,row == n,此时将已经完成皇后排列的当前子集cur放入res;那么res中总共有多少个子集cur呢?请看下一期走近科学,N-Queens II

Solution
  1. class Solution {
  2. ArrayList<ArrayList<String>> solveNQueens(int n) {
  3. ArrayList<ArrayList<String>> res = new ArrayList();
  4. ArrayList<String> cur = new ArrayList();
  5. StringBuilder sb = new StringBuilder();
  6. for (int i = 0; i < n; i++) sb.append('.');
  7. for (int i = 0; i < n; i++) cur.add(sb.toString());
  8. helper(n, 0, cur, res);
  9. return res;
  10. }
  11. public void helper(int n, int row, ArrayList<String> cur, ArrayList<ArrayList<String>> res) {
  12. if (row == n) {
  13. ArrayList<String> toAdd = new ArrayList();
  14. for (int i = 0; i < cur.size(); i++) toAdd.add(cur.get(i));
  15. res.add(toAdd);
  16. return;
  17. }
  18. for (int j = 0; j < n; j++) {
  19. if (isValid(n, cur, row, j)) {
  20. StringBuilder sb = new StringBuilder(cur.get(row));
  21. sb.setCharAt(j, 'Q');
  22. cur.set(row, sb.toString());
  23. helper(n, row+1, cur, res);
  24. sb.setCharAt(j, '.');
  25. cur.set(row, sb.toString());
  26. }
  27. }
  28. }
  29. public boolean isValid(int n, ArrayList<String> cur, int row, int col) {
  30. for (int i = 0; i < row; i++) {
  31. for (int j = 0; j < n; j++) {
  32. if (cur.get(i).charAt(j) == 'Q' && (j == col || Math.abs(row-i) == Math.abs(col-j))) return false;
  33. }
  34. }
  35. return true;
  36. }
  37. };
复制代码
N-Queens II Problem

Follow up for N-Queens problem.

Now, instead outputting board configurations, return the total number of distinct solutions.

Example

For n=4, there are 2 distinct solutions.

Note

N-Queens一模一样,用计数器统计能完整递归的次数:每次对子集cur递归到row == n时,只要计数器count++即可。

Solution
  1. class Solution {
  2. int count = 0;
  3. int totalNQueens(int n) {
  4. ArrayList<ArrayList<String>> res = new ArrayList();
  5. ArrayList<String> cur = new ArrayList();
  6. StringBuilder sb = new StringBuilder();
  7. for (int i = 0; i < n; i++) sb.append('.');
  8. for (int i = 0; i < n; i++) cur.add(sb.toString());
  9. return helper(0, n, cur);
  10. }
  11. int helper(int row, int n, ArrayList<String> cur) {
  12. if (row == n) count++;
  13. for (int j = 0; j < n; j++) {
  14. if (isValid(row, j, n, cur)) {
  15. StringBuilder sb = new StringBuilder(cur.get(row));
  16. sb.setCharAt(j, 'Q');
  17. cur.set(row, sb.toString());
  18. helper(row+1, n, cur);
  19. sb.setCharAt(j, '.');
  20. cur.set(row, sb.toString());
  21. }
  22. }
  23. return count;
  24. }
  25. boolean isValid(int row, int col, int n, ArrayList<String> cur) {
  26. for (int i = 0; i < row; i++) {
  27. for (int j = 0; j < n; j++) {
  28. if (cur.get(i).charAt(j) == 'Q' && (col == j || Math.abs(row-i) == Math.abs(col-j))) return false;
  29. }
  30. }
  31. return true;
  32. }
  33. }
复制代码

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-6-27 18:27

Copyright 2015-2025 djqfx

返回顶部