LeetCode051——N皇后

版权声明:版权所有,转载请注明原网址链接。 https://blog.csdn.net/qq_41231926/article/details/82781370

我的LeetCode代码仓:https://github.com/617076674/LeetCode

原题链接:https://leetcode-cn.com/problems/n-queens/description/

题目描述:

知识点:递归、回溯

思路:采用回溯法穷尽所有不同的n皇后问题的解决方案

N皇后问题是一个很经典的用回溯法解决的问题。

首先要明确N皇后问题的条件:

在n * n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,罗列索引可能的摆法。

针对这个条件,我们可以得出一个结论,每一行有且仅有一个皇后

这里我们定义一个n * n的visited数组,来定义位置(i, j)是否可以放置皇后,true表示不能放置皇后,false表示可以放置皇后。

在递归函数solveNQueens中,传入的参数hashMap表示第key行的皇后放置在了第value列,m表示我们将要摆放第m行的皇后,n表示皇后总数,具体请见JAVA代码。

递归终止条件

当m == n时,说明我们将要摆放第n行的皇后,而数组的行数是从0开始计数的,只有n - 1行,因此此时我们已经完成了所有皇后的放置,由此时的hashMap构建出一个解决方案。

递归过程

对于第m行我们根据规则:任意两个皇后都不能处于同一行、同一列或同一斜线上,寻找可以放置皇后的位置。

注意相关变量的手动回溯问题。

对于hashMap很容易回溯,直接移除第m行的皇后即可。

但对于visited数组,回溯过程不是很容易。因为对于新增的皇后,其会使得原本一些可以放置皇后的区域变成不能放置皇后的区域。在回溯过程中,我们要将这些由于新增的皇后而改变属性的区域回溯。但是也有一些区域在新增皇后之前就已经是不能放置皇后的区域,新增的皇后虽然也使得其变成不能放置皇后的区域,但在这前后并不改变该区域的属性,因此我们需要一个变量来标记哪些区域是由于新增的皇后而由可以放置皇后的区域变成了不能放置皇后的区域。这是有点复杂的。

因此,我们采用另一种做法避免了这个回溯过程。我们每一次都新建一个tempVisited数组来传递,就避免了对原数组visited的修改,也就省去了visited数组的手动回溯过程。但这种做法不可避免地在每次回溯过程中消耗了大量的空间和时间。

对于时间复杂度而言,是O(n ^ n)级别的。而空间复杂度就是递归深度,本应该是O(n)级别的,但由于每一次递归过程中为了避免对visited数组的手动回溯过程,我们新建了一个tempVisited数组,因此总的空间复杂度是O(n ^ 3)级别的。

JAVA代码:

public class Solution {

	List<List<String>> listList;
	
	public List<List<String>> solveNQueens(int n) {
		listList = new ArrayList<>();
		boolean[][] visited = new boolean[n][n];
		solveNQueens(new HashMap<>(), 0, n, visited);
		return listList;
	}
	
	/*
	 * hashMap-------The queen in row key is in column value
	 * we are going to put the mth queen
	 * n represents the total quantity of the queen
	 */
	private void solveNQueens(HashMap<Integer, Integer> hashMap, int m, int n, boolean[][] visited) {
		if(m == n) {
			List<String> list = new ArrayList<>();
			for (int i = 0; i < n; i++) {
				String string = "";
				for (int j = 0; j < n; j++) {
					if(hashMap.containsKey(i) && hashMap.get(i) == j) {
						string += "Q";
					}else {
						string += ".";
					}
				}
				list.add(string);
			}
			listList.add(list);
			return;
		}
		for (int i = 0; i < n; i++) {
			if(!visited[m][i]) {
				hashMap.put(m, i);
				boolean[][] tempVisited = new boolean[n][n];
				for (int j = 0; j < n; j++) {
					for (int k = 0; k < n; k++) {
						tempVisited[j][k] = visited[j][k];
					}
				}
				for (int j = 0; j < n; j++) {
					tempVisited[j][hashMap.get(m)] = true;
					tempVisited[m][j] = true;
					for (int k = 0; k < n; k++) {
						if((Math.abs(j - m) == Math.abs(k - hashMap.get(m)))) {
							tempVisited[j][k] = true;
						}
					}
				}
				solveNQueens(hashMap, m + 1, n, tempVisited);
				hashMap.remove(m);
			}
		}
	}
}

LeetCode解题报告:

猜你喜欢

转载自blog.csdn.net/qq_41231926/article/details/82781370
今日推荐