Leetcode之回溯法专题-51. N皇后(N-Queens)

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

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

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

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

示例:

输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."], ["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。 分析:输入一个N,求在这个N*N的面板里,N皇后的解法。要求是,放置了一个皇后时,该皇后的 行 列 不能存在其他皇后,且2个对角线上也不能有皇后。
利用回溯法可以解答这一题,首先初始化一个N*N的数组,并在其值上设置成'.'。
char mp[][] = new char[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
mp[i][j] = '.';
}
}
然后我们new一个存答案的List,
List<List<String>> ans = new ArrayList<>();

在写DFS之前,我们需要写一个boolean型的ok函数,用于判断一个棋盘是否符合要求:
public boolean ok(char[][] mp, int len, int x, int y) {
// check row
for (int i = 0; i < len; i++) {
if (i == y)
continue;
if (mp[x][i] == 'Q')
return false;
} // check col
for (int i = 0; i < len; i++) {
if (i == x)
continue;
if (mp[i][y] == 'Q')
return false;
} // x=1 y=3
int cnt = 0;
int up = 0;
int down = 0; for(int i=y+1;i<len;i++){
up = (++cnt)*-1+x;
down = cnt*1+x; if(up<len && up>=0){
//System.out.println("mp[up][i]=["+up+"]["+i+"]");
if(mp[up][i]=='Q')
return false;
} if(down>=0 && down<len){
//System.out.println("mp[down][i]=["+down+"]["+i+"]");
if(mp[down][i]=='Q'){
return false;
}
}
} //System.out.println("other");
cnt = 0;
for(int i=y-1;i>=0;i--){
up = (++cnt)*-1+x;
down = cnt*1+x; if(up<len && up>=0){
//System.out.println("mp[up][i]=["+up+"]["+i+"]");
if(mp[up][i]=='Q')
return false;
} if(down>=0 && down<len){
//System.out.println("mp[down][i]=["+down+"]["+i+"]");
if(mp[down][i]=='Q'){
return false;
}
}
} return true;
}


下一步开始写dfs函数,
第一个参数是mp数组,是这一副棋盘,
第二个参数是n,代表的是棋盘的大小,
第三个参数是i,把2维的矩阵转换为1维了,例如i=1就对应着(0,1)这个点,以此类推。
第四个参数是queen,用来存现在放的棋子的个数。
public void dfs(char[][] mp, int len, int i,int queen) {
int x = i / len;
int y = i % len; if ((x >= len || y >= len)) {
if(queen!=len) return;
List<String> list = new ArrayList<>();
for (int a = 0; a < len; a++) {
String tmp = "";
for (int b = 0; b < len; b++) {
tmp += mp[a][b];
}
list.add(tmp);
}
ans.add(list);
return;
}
dfs(mp,len,i+1,queen);
if (ok(mp, len, x, y)) {
mp[x][y] = 'Q';
dfs(mp, len, i + 1,queen+1);
mp[x][y] = '.';
} }

整合一下,最后的AC代码为:

class Solution {
List<List<String>> ans = new ArrayList<>(); public List<List<String>> solveNQueens(int n) { char mp[][] = new char[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
mp[i][j] = '.';
}
}
dfs(mp, n, 0,0); return ans;
} public void dfs(char[][] mp, int len, int i,int queen) {
int x = i / len;
int y = i % len; if ((x >= len || y >= len)) {
if(queen!=len) return;
List<String> list = new ArrayList<>();
for (int a = 0; a < len; a++) {
String tmp = "";
for (int b = 0; b < len; b++) {
tmp += mp[a][b];
}
list.add(tmp);
}
ans.add(list);
return;
}
dfs(mp,len,i+1,queen);
if (ok(mp, len, x, y)) {
mp[x][y] = 'Q';
dfs(mp, len, i + 1,queen+1);
mp[x][y] = '.';
} } public boolean ok(char[][] mp, int len, int x, int y) {
// check row
for (int i = 0; i < len; i++) {
if (i == y)
continue;
if (mp[x][i] == 'Q')
return false;
} // check col
for (int i = 0; i < len; i++) {
if (i == x)
continue;
if (mp[i][y] == 'Q')
return false;
} // x=1 y=3
int cnt = 0;
int up = 0;
int down = 0; for(int i=y+1;i<len;i++){
up = (++cnt)*-1+x;
down = cnt*1+x; if(up<len && up>=0){
//System.out.println("mp[up][i]=["+up+"]["+i+"]");
if(mp[up][i]=='Q')
return false;
} if(down>=0 && down<len){
//System.out.println("mp[down][i]=["+down+"]["+i+"]");
if(mp[down][i]=='Q'){
return false;
}
}
} //System.out.println("other");
cnt = 0;
for(int i=y-1;i>=0;i--){
up = (++cnt)*-1+x;
down = cnt*1+x; if(up<len && up>=0){
//System.out.println("mp[up][i]=["+up+"]["+i+"]");
if(mp[up][i]=='Q')
return false;
} if(down>=0 && down<len){
//System.out.println("mp[down][i]=["+down+"]["+i+"]");
if(mp[down][i]=='Q'){
return false;
}
}
} return true;
} }

Leetcode之回溯法专题-51. N皇后(N-Queens)的更多相关文章

  1. Leetcode之回溯法专题-52. N皇后 II(N-Queens II)

    Leetcode之回溯法专题-52. N皇后 II(N-Queens II) 与51题的代码80%一样,只不过52要求解的数量,51求具体解,点击进入51 class Solution { int a ...

  2. Leetcode之回溯法专题-216. 组合总和 III(Combination Sum III)

    Leetcode之回溯法专题-216. 组合总和 III(Combination Sum III) 同类题目: Leetcode之回溯法专题-39. 组合总数(Combination Sum) Lee ...

  3. Leetcode之回溯法专题-212. 单词搜索 II(Word Search II)

    Leetcode之回溯法专题-212. 单词搜索 II(Word Search II) 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单 ...

  4. Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning)

    Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning) 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. ...

  5. Leetcode之回溯法专题-90. 子集 II(Subsets II)

    Leetcode之回溯法专题-90. 子集 II(Subsets II) 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入 ...

  6. Leetcode之回溯法专题-79. 单词搜索(Word Search)

    Leetcode之回溯法专题-79. 单词搜索(Word Search) 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元 ...

  7. Leetcode之回溯法专题-78. 子集(Subsets)

    Leetcode之回溯法专题-78. 子集(Subsets) 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = ...

  8. Leetcode之回溯法专题-77. 组合(Combinations)

    Leetcode之回溯法专题-77. 组合(Combinations)   给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合. 示例: 输入: n = 4, k = 2 输 ...

  9. Leetcode之回溯法专题-47. 全排列 II(Permutations II)

    Leetcode之回溯法专题-47. 全排列 II(Permutations II) 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2] ...

随机推荐

  1. 小白学python-day01-电脑结构知识

    作为一个”0“基础的经济学学士来说,专业分类选择了经统,多多少少和计算机有点关系,从今天开始学习python. 但行努力,莫问前程. day01学习电脑结构等知识. 因为这些知识是 有规则的,客观的文 ...

  2. python课堂整理21---初识装饰器

    一.装饰器: 本质就是函数,功能:为其他函数添加附加功能 原则: 1.不能修改被装饰函数的源代码 2.不能修改被修饰函数的调用方式 一个简单的装饰器 import time def timmer(fu ...

  3. MySQL不停地自动重启怎么办

    近期,测试环境出现了一次MySQL数据库不断自动重启的问题,导致的原因是强行kill -9 杀掉数据库进程导致,报错信息如下: --24T01::.769512Z [Note] Executing ' ...

  4. C++判断图像中一点是否在矩形中

    需要判断出四条之间组成的矩形的范围,其中矩形的边缘可能是倾斜不平行于x或者y轴. 考虑和很久,参考博客http://blog.csdn.net/dapengbusi/article/details/5 ...

  5. 通过mark和reset方法重复利用InputStream

    InputStreammarkreset 在这篇博客中我们已经简单的知道可以通过缓存InputStream来重复利用一个InputStream,但是这种方式的缺点也是明显的,就是要缓存一整个Input ...

  6. Ubuntu 执行chmod -R 777 / 挽救方法

    mgj怎么会有堪比rm -rf /*这样神奇的命令,本想着把当前目录下的权限改为777,没想到把整个/目录下全设成777了,直觉告诉我好像哪里有些不对劲,好在一顿xjb折腾最终弄好了,应该没啥大问题, ...

  7. 基于vue2.0搭建项目流程

    搭建vue2.0项目--myproject 一. 环境搭建: 1 打开命令行(cmd) 2 安装node node官网 3 安装 vue-cli步骤如下: npm install -g vue-cli ...

  8. ABP实现EF执行SQL(增删改查)解决方案

    前言 一般情况下,使用EF中的语法可以帮助我们完成绝大部分业务,但是也有特殊的情况需要直接执行的Sql语句.比如,我们的业务过于复杂繁琐,或是有些业务使用EF操作时比较复杂,但是使用的Sql时会很简单 ...

  9. java并发编程(四)----(JUC)Lock锁初探

    首先我们来回忆一下上一节讲过的synchronized关键字,该关键字用于给代码段或方法加锁,使得某一时刻它修饰的方法或代码段只能被一个线程访问.那么试想,当我们遇到这样的情况:当synchroniz ...

  10. 洛谷 P2016 战略游戏

    题意简述简述 求一棵树的最小点覆盖 题解思路 树形DP dp[i][0]表示第i个点覆盖以i为根的子树的最小值,且第i个点不放士兵 dp[i][1]表示第i个点覆盖以i为根的子树的最小值,且第i个点放 ...