练习下经典的N皇后问题 java

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
在这里插入图片描述

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

示例:

输入: 4
输出: [
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],

["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
解释: 4 皇后问题存在两个不同的解法。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码

目前想到的是这种解法,效率一般。

    public static void main(String[] args) {
//        printList(solveNQueens(4));
        printList(solveNQueens(5));
    }


    private static List<List<String>> resList=new ArrayList<>();

    private static Integer N;

    public static List<List<String>> solveNQueens(int n) {
        resList=new ArrayList<>();
        N=n;

        List<Integer> queenIndex=new ArrayList<>();

        for (int i = 0; i <N ; i++) {
            queenIndex.add(i);
            dfs(queenIndex);
            queenIndex.remove(queenIndex.size()-1);
        }


        return resList;
    }

    //n皇后问题必然是每一行都有皇后。
    //用一个queenIndex表示 皇后在每个行出现的位置。
    //我们只需要在每一行找皇后能出现的位置,然后进入下一行。
    //当进行到queenIndex为N时返回结果。
    public static void dfs(List<Integer> queenIndex){

        //获取到解
        if(queenIndex.size()==N){
            addAnswer(queenIndex);
            return;
        }

        List<Integer> retain=getRetain(queenIndex); //当前行可用的位置
        if (retain.size()==0) return; //没有可用位置返回

        for (int i = 0; i < retain.size(); i++) {
             //添加解,进入下一层
             queenIndex.add(retain.get(i));
             dfs(queenIndex);
             queenIndex.remove(queenIndex.size()-1); //回溯
        }


    }

    //将当前解添加到答案中
    public static void addAnswer(List<Integer> queenIndex){
        List<String> list=new ArrayList<>();
        for (int i = 0; i < N; i++) {
            StringBuilder builder=new StringBuilder();
            for (int j = 0; j < N; j++) {
                if(j==queenIndex.get(i)){
                    builder.append("Q");
                }else {
                    builder.append(".");
//                    builder.append("O");
                }
            }
            list.add(builder.toString());
        }
        resList.add(list);

    }

    //获取下一行可以选的位置数的列表
    public static List<Integer> getRetain(List<Integer> queenIndex){
        Set<Integer> set=new HashSet<>(); //当前行可用的位置
        int row=queenIndex.size(); //获取当前行
        for (int i = 0; i < queenIndex.size(); i++) {
            set.add(queenIndex.get(i));
            set.add(queenIndex.get(i)-row+i);
            set.add(queenIndex.get(i)+row-i);
        }
        List<Integer> retain=new ArrayList<>();
        for (int i = 0; i <N ; i++) {
            if(!set.contains(i)){
                retain.add(i);
            }
        }
        return retain;
    }

    //写一个打印方法检查数据
    public static void printList(List<List<String>> lists){
        for (int i = 0; i < lists.size(); i++) {
            List<String> list=lists.get(i);
            for (int j = 0; j < list.size(); j++) {
                System.out.println(list.get(j));
            }
            System.out.println("======================");
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值