回溯算法——N皇后问题(极大幅降低空间复杂度!!!)

今天在刷LeetCode时,遇到了一个N皇后的问题,问题如下:
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击,即同一横行、数列、斜线不能出现两个皇后。需要输出所有的摆放情况。输出格式为:每个方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
这是一个非常经典的应用回溯算法的题目,看了网上一些的解答,空间复杂度大多都是O(n^2),下面是我的解法,使得空间复杂度降低为O(n):
为了解决这个问题,我们建立了三个数组row[n],first[2n-1],second[2n-1](三个数组取值,只有0或1)以及变量flag。flag是表示当前我们要在棋盘上放置第flag行的皇后,
row[i]=0 表示第i列没有放置皇后
row[i]=1 表示第i列已放置皇后
first[i-flag+n-1]=0 表示(flag,i)坐标上的主对角线没有放置皇后
first[i-flag+n-1]=1 表示(flag,i)坐标上的主对角线已放置皇后
second[i+flag]==0 表示(flag,i)坐标上的副对角线没有放置皇后
second[i+flag]==1 表示(flag,i)坐标上的副对角线已放置皇后
(主对角线:左上到右下;副对角线:右上到坐下)
这个地方只需要O(n)空间复杂度就可以来判别(flag,i)处是否可以放置皇后,时间消耗也会大大降低,理解了上面的这个步骤就很简单了,剩下的就是回溯算法的应用了。

//插入某一行的输出格式
public static String s(int i,int n) {
		String string="";
		for (int j = 0; j < n; j++) {
			if (j==i) {
				string+="Q";
			}else {
				string+=".";
			}
		}
		
		return string;
	}

	public static void Queens(int n,List<List<String>> result,List<String> list,int []row,int []first,int []second,int flag) {
		if (flag==n) {
			//此时,最后一行也追加到了list中,则可以把list存储的方案追加到最终结果
			result.add(new ArrayList<String>(list));
			
		}else {
			for (int i = 0; i < n; i++) {
				if (row[i]==0&&first[i-flag+n-1]==0&&second[i+flag]==0) {
					//如果该处可以放置皇后
					row[i]=1;
					first[i-flag+n-1]=1;
					second[i+flag]=1;
					flag++;
					//把该行的格式追加到list中
					list.add(s(i, n));
					//开始下一行的放置皇后
					Queens(n, result, list, row, first, second, flag);
					//撤销本次的放置
					row[i]=0;
                    flag--;
					first[i-flag+n-1]=0;
					second[i+flag]=0;
					list.remove(list.size()-1);
				}
			}
		}
	}
	
	public static List<List<String>> solveNQueens(int n) {
		List<List<String>> result=new ArrayList<List<String>>();
		int []row=new int[n];
		int []first=new int[n*2-1];
		int []second=new int[n*2-1];
		List<String> list=new ArrayList<String>();
		Queens(n, result, list, row, first, second,0);
		return result;
	}
	测试代码如下:
public static void main(String[] args) {
		// TODO Auto-generated method stub
		//n为输入的皇后个数
		int n=4;
		List<List<String>> result=solveNQueens(n);
		for (int i = 0; i < result.size(); i++) {
			for (int j = 0; j < result.get(i).size(); j++) {
				System.out.println(result.get(i).get(j));
			}
			System.out.println("");
		}
	}

输出结果如下:
.Q…
…Q
Q…
…Q.

…Q.
Q…
…Q
.Q…

下面是在LeetCode的运行结果:
回溯算法——N皇后问题(极大幅降低空间复杂度!!!)_第1张图片

PS:激动!第一次写博客大家多多包涵,有问题随时联系我,谢谢大嘎(鞠躬)!

你可能感兴趣的:(回溯算法,N皇后,Java,LeetCode,空间复杂度)