leetcode n-queens
N皇后是一个十分经典的问题。
这题一个经典的解法就是回溯法。
一开始使用回溯法的话。陷入了两个误区。
第一,每次回溯都从第一个点开始计算,其实完全没必要。
第二,每次回溯都将当前解空间复制一遍。其实也没有必要。
上网搜了一下解法。核心思想为,因为N皇后问题限制每行只能放一个皇后。所以,考虑以行为维度考虑问题而不是以
点为维度考虑问题。
对于每次递归,检索当前行内所有的点,如果找到一个点就进入下一行。如果当前行所有点都无效,则直接返回。
那么对于解空间的问题。一开始觉得每次分裂出一个新的解,就需要把其上一行的解空间复制一遍,以保证其没有冲突。
其实没有必要这么做,回溯法一个重要的点就是,从头到尾只使用一个解空间,只是当你完成某个维度的检索,返回上一级
维度时,将当前维度的解空间清空即可。这一点在上一个博文permuations中也有体现,他在完成一个维度的检索之后,
再把交换过的元素交换回来。
下面给出代码
import java.util.ArrayList; import java.util.List; public class Solution2 { /** * @param args */ public List<List<String>> solveNQueens(int n) { ArrayList<List<String>> result=new ArrayList<List<String>>(); int [][]nums=new int[n][n]; f(0,0,nums,result); return result; } private void f(int x,int y,int[][] nums, ArrayList<List<String>> result) { //p(nums); // System.out.println("--------------"); for(int i=0;i<nums.length;i++) { if(test(nums,x,i)) { nums[x][i]=1; if(x==nums.length-1) { result.add(Convert(nums)); break; } f(x+1,0,nums,result); } nums[x][i]=0; } for(int i=0;i<nums.length;i++) nums[x][i]=0; } private boolean test(int [][]solution,int x,int y) { for(int i=0;i<solution.length;i++) for(int j=0;j<solution[i].length;j++) { if(solution[i][j]==1) { if(x==i||y==j) return false; double gradient=(double)(y-j)/(double)(x-i); if(gradient==1.0||gradient==-1.0) return false; } } return true; } private ArrayList<String> Convert(int [][]solution) { ArrayList<String> result=new ArrayList<String>(); for(int i=0;i<solution.length;i++) { String tmp=""; for(int j=0;j<solution[i].length;j++) { if(solution[i][j]==0) tmp+="."; else tmp+="Q"; } result.add(tmp); } return result; } }