N皇后问题

今天做了leetcode中两道关于N皇后的题目:
51. N-Queens
52. N-Queens II
这是回溯法的经典应用,自己不太会做…主要是研究了下别人的思路,然后自己写了写~

N-Queens II

Follow up for N-Queens problem.

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

(1)简单易懂版本(或者利用循环将其改为非递归形式)

public class Solution {
    int sum = 0;
    public int totalNQueens(int n) {
        int[] y = new int[n];//解向量,代表皇后被放置在i+1行y[i]+1列(0~n-1/1~n)
        backtracking(1,n,y);
        return sum;
    }

    private boolean place(int row, int[] y){
        //row介于1-n之间,代表目前在讨论第几行的皇后
        for(int i=0;i<row-1;i++){
            //如果当前的皇后和之前的皇后位于同一列或者对角线(行差等于列差)
            if(y[i]==y[row-1] || Math.abs(i-row+1)==Math.abs(y[i]-y[row-1])) return false;
        }
        return true;
    }

    //回溯,需要递归调用
    private void backtracking(int row,int n, int[] y){
        if(row > n) sum++;
        else{
            //在第row行选择合适的一列把第row个皇后放下
            for(int i=0;i<n;i++){
                y[row-1] = i;
                if(place(row,y)) backtracking(row+1,n,y);//位置合适,则开始考虑下一行
            }
            //运行至此,表示没有找到合适的位置,将会返回到上一级的backtracking语句行,
            //重新摆放上一个皇后,继续寻找可能得解
        }
    }
}

(2)在discuss里看到一种利用位运算降低空间复杂度和时间复杂度的算法,之前也使用过这种手段,即利用每一位(’0’或者’1’)表示一种状态,每次都在更新。

public class Solution {
    int sum = 0;
    public int totalNQueens(int n) {
        backtracking(0,n,0,0,0);
        return sum;
    }

    //回溯,需要递归调用
    //row: 目前讨论的是在第row行放置queen(row介于0~n-1)
    //n: 一共需要放置n个queen
    //以棋盘左下角为原点坐标
    //colHasQueen:标记此行之前的哪些column已经放置了皇后,
    //            如有放置在(r,c)坐标上的皇后则colHasQueen[c]=1;
    //diagHasQueen:标记此行之前的哪些主对角线已经放置了皇后,
    //             如有放置在(r,c)坐标上的皇后则diagHasQueen[n-1+r-c]=1;->棋盘格子向对角线做垂线映射得到
    //antidiagHasQueen:标记此行之前的哪些副对角线已经放置了皇后,
    //                 如有放置在(r,c)坐标上的皇后则antidiagHasQueen[r+c]=1;->棋盘格子向其做垂线映射得到

    private void backtracking(int row,int n, int colHasQueen, int diagHasQueen, int antidiagHasQueen){
        if(row == n) sum++;
        else{
            for(int i=0;i<n;i++){
                boolean isColSafe = ((1<<i)&colHasQueen)==0;
                boolean isDiagSafe = ((1 << (n - 1 + row - i)) & diagHasQueen)==0;
                boolean isAntiDiagSafe = ((1 << (row + i)) & antidiagHasQueen)==0;
                if(isColSafe&&isDiagSafe&&isAntiDiagSafe){
                    backtracking(row+1, n, (1<<i)|colHasQueen, ((1 << (n - 1 + row - i)) | diagHasQueen), (1 << (row + i)) | antidiagHasQueen);
                }
            }
            //运行至此,表示没有找到合适的位置,将会返回到上一级的backtracking语句行,
            //重新摆放上一个皇后,继续寻找可能得解
        }
    }
}

51. N-Queens

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.

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

[
[“.Q..”, // Solution 1
“…Q”,
“Q…”,
“..Q.”],

[“..Q.”, // Solution 2
“Q…”,
“…Q”,
“.Q..”]
]
写完上面那个,下面的就好些一点啦~重点是要选好数据结构去存储solutions。

public class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> result = new ArrayList<List<String>>();
        char[][] curSolution = new char[n][n];
        backtracking(0,n,0,0,0,result, curSolution);
        return result;
    }

    private void backtracking(int row,int n, int colHasQueen, int diagHasQueen, int antidiagHasQueen, List<List<String>> result, char[][] curSolution){
        if(row == n){
            List<String> cur = new ArrayList<String>();
            for(char[] tmp:curSolution){
                cur.add(String.valueOf(tmp));
            }
            result.add(cur);
        }
        else{
            for(int i=0;i<n;i++){
                boolean isColSafe = ((1<<i)&colHasQueen)==0;
                boolean isDiagSafe = ((1 << (n - 1 + row - i)) & diagHasQueen)==0;
                boolean isAntiDiagSafe = ((1 << (row + i)) & antidiagHasQueen)==0;
                if(isColSafe&&isDiagSafe&&isAntiDiagSafe){
                    curSolution[row][i] = 'Q';
                    backtracking(row+1, n, (1<<i)|colHasQueen, ((1 << (n - 1 + row - i)) | diagHasQueen), (1 << (row + i)) | antidiagHasQueen, result, curSolution);
                    curSolution[row][i]='.';
                }
            }
        }
    }
}

要学的东西太多了…希望自己每天多打打鸡血,不要像以前那样懒…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值