LeetCode:N-Queens

26 篇文章 0 订阅
8 篇文章 0 订阅
/**
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.

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

[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]
题目大意:输出所有可能的皇后摆放方式
**/

public class Solution {
    public ArrayList<String[]> solveNQueens(int n) {
        return solve1(n);        
    }

    //========================== solve1 ================================
    //先做了N-Queens II才回头做这题,直接改了一部分就好了
    
    //O(n^3) = O(n) * O(n) * O(n)
    //由于要遍历所有可能性,所以复杂度颇高:遍历行 * 遍历列 * 检查
    //其实就是个深度优先遍历
    /*
      回溯法解N皇后问题
      使用一个一维数组表示皇后的位置
      其中数组的下标表示皇后所在的行
      数组元素的值表示皇后所在的列
      这样设计的棋盘,所有皇后必定不在同一行
     
      假设前n-1行的皇后已经按照规则排列好
      那么可以使用回溯法逐个试出第n行皇后的合法位置
      所有皇后的初始位置都是第0列
      那么逐个尝试就是从0试到N-1
      如果达到N,仍未找到合法位置
      那么就置当前行的皇后的位置为初始位置0
      然后回退一行,且该行的皇后的位置加1,继续尝试
      如果目前处于第0行,还要再回退,说明此问题已再无解
     
      如果当前行的皇后的位置还是在0到N-1的合法范围内
      那么首先要判断该行的皇后是否与前几行的皇后互相冲突
      如果冲突,该行的皇后的位置加1,继续尝试
      如果不冲突,判断下一行的皇后
      如果已经是最后一行,说明已经找到一个解,输出这个解
      然后最后一行的皇后的位置加1,继续尝试下一个解
    */
    
    private int[] place = null;
    pirvate ArrayList<String[]> result = null;
    
    private ArrayList<String[]> solve1(int n){
        //n长度的数组,存储着每一行的皇后的位置
        place = new int[n];
        //结果的个数
        result = new ArrayList<String[]>();
        
        //递归求解
        loop(n, 0);
        
        return result;
    }
    private void loop(int n, int depth){
        //如果已经放下最后一个皇后,则解决方案多一个
        //这里形成详尽的解决方案,而不只是计数
        if(depth == n){
            result.add(buildResult());
            return;
        }
        
        //在当前行进行遍历,选择不同的列
        for(int i=0; i<n; i++){
            //如果当前列允许放下皇后,那就放下并且递归检查下一个行
            if(checkOK(depth, i)){
                place[depth] = i;
                loop(n, depth+1);
            }
        }
    }
    //检查在当前的depth行的第i列是否可放皇后
    private boolean checkOK(int depth, int col){
        for(int i=0; i<depth; i++)
            if(place[i]==col                        //同一列
                    || place[i]+(depth-i) == col    //右斜线
                    || place[i]-(depth-i) == col)   //左斜线
                return false;
        
        return true;
    }
    //根据place[]所标识的皇后位置创造String[]
    //这里可以进行调优,使用StringBuilder而非直接使用String
    private String[] buildResult(){
        String[] strResult = new String[place.length];
        for(int i=0; i<place.length; i++){
            String tmp = "";
            for(int j=0; j<place.length; j++){
                if(j == place[i])
                    tmp += "Q";
                else
                    tmp += ".";
            }
            strResult[i] = tmp;
        }
        return strResult;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值