leetcode 每日一题 51 N皇后

本文介绍了使用递归和回溯法解决LeetCode上的N皇后问题。通过设置列数组、斜线数组和反斜线数组来剪枝,提高算法效率。当找到满足N皇后条件的解时,将其添加到答案中。代码实现详述了如何判断每个皇后位置的合法性并进行递归操作。
摘要由CSDN通过智能技术生成

在这里插入图片描述
题目链接:https://leetcode-cn.com/problems/n-queens/

每日一题碰到 N皇后II 了,先做一下 N皇后。

主要思路就是递归加回溯了,真·暴力解决也很简单,直接一直递归最后判断是否满足 N皇后 的条件即可。

这里考虑尽可能的剪枝来降低时间消耗,首先题目给出 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上 。所以可以用这个条件来判断满足进入递归的条件,开始我的思路是每次填充一个皇后时,将她的横行、纵行、斜线行和反斜线行设置标记,下一层填充皇后时判断当前位置是否可以放置,可以就进入下一层递归,不能就判断下一个位置。这样一直递归到最后一行时,如果第 n-1 行填充了,说明这个解法可行,添加到 答案 中。这里因为一行一行的递归,所以横行的判断是多余的

但是这样每次填充一个皇后之后,设置标记会浪费很多时间,所以优化了一下。这里选择分别用一个 列数组、斜线数组 和 反斜线数组 来记录当前是否可以填充皇后。
在这里插入图片描述
这里用 boolean[] column 来存储列的情况,用 boolean[] slash 来存储斜行的情况,用 boolean[] backslash 来存储反斜行的情况。两边的矩阵横轴上的是列,纵轴上的是行,可以看到左边直接用 行数 + 列数 得到的数字正好是对应的斜行。右边需要对列进行处理,可以看到是用绿色的坐标就正好是对应的反斜行数,这里正好可以用 n-1-列数 来代替 列数 。这样判断到一个 皇后 填充的位置时,可以得到他的 列数、斜行数 和 反斜行数。假设 皇后 填充位置为 [ i , j ] ,那么可以得到她的 列数 = j斜行数 = i + j斜行数 = n - 1 - j + i。然后判断 column[列数]slash[斜行数]backslash[反斜行数] 是否都为 false ,如果是则可填充,否则判断下一个。
步骤类似下图:
在这里插入图片描述
每行会遍历所有列,如果某个位置满足列、斜行、反斜行的要求,那么加入该点进行下一行的递归,如果不满足就直接查看该行的下一个位置。
以上总结为代码如下:

package com.company;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class lc51 {
    List<List<String>> ans = new LinkedList<>();
    public List<List<String>> solveNQueens(int n) {
        if(n==0)return ans;
        char[][] chars= new char[n][n];
        for(char[] ch : chars){
            Arrays.fill(ch,'.');
        }
        boolean[] column = new boolean[n];
        boolean[] slash = new boolean[2*n-1];
        boolean[] backslash = new boolean[2*n-1];
        find(chars,column,slash,backslash,0);
        return ans;
    }
    public void find(char[][] chars,boolean[] column,boolean[] slash,boolean[] backslash,int i){
        if(i==chars.length){
            List<String> list = new LinkedList<>();
            for(char[] ch : chars){
                list.add(String.valueOf(ch));
            }
            ans.add(list);
        }else{
            for (int j = 0; j < chars.length; j++) {
                int slashTemp = i+j;
                int backslashTemp = chars.length-1-j+i;
                if(!column[j]&&!slash[slashTemp]&&!backslash[backslashTemp]){
                    chars[i][j] = 'Q';
                    column[j] = true;
                    slash[slashTemp] = true;
                    backslash[backslashTemp] = true;
                    find(chars,column,slash,backslash,i+1);
                    chars[i][j] = '.';
                    column[j] = false;
                    slash[slashTemp] = false;
                    backslash[backslashTemp] = false;
                }

            }
        }
    }
}

最终顺利通过
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值