leetCode 51.N-Queens (n皇后问题) 解题思路和方法

N-Queens

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens‘ placement, where ‘Q‘ and ‘.‘ both indicate a queen and an empty space respectively.

For example,

There exist two distinct solutions to the 4-queens puzzle:

[

[".Q..",  // Solution 1

"...Q",

"Q...",

"..Q."],

["..Q.",  // Solution 2

"Q...",

"...Q",

".Q.."]

]

思路:本题大的方法上我想到了两个思路,第一个是将n皇后问题转化为全排列问题。

设x[n]为一组解。代表第i行第x[i]列放置了皇后。

所以求出全排列,然后推断是否合法就可以。

代码例如以下(没有Ac,进一步优化之后应该是能够Ac的):

public class Solution {
        public List<List<String>> solveNQueens(int n) {
    	List<List<String>> returnList = new ArrayList<List<String>>();
    	/**
    	 * x[i]为第i列存放的位置
    	 * 转化为0-(n-1)的全排列,然后推断全排列的位置是否合法就可以
    	 */
        int[] num = new int[n];
        int i = 0;
        while(i < n){
        	num[i] = i;//填充数组为0-(n-1)
        	i++;
        }
        List<List<Integer>> list = permuteUnique(num);
        for(List<Integer> al : list){//对每一组数据处理
        	for(i = 0; i < al.size(); i++){
        		if(!check(al, i, al.get(i)))
        			break;//不合法跳出
        	}
        	if(i == n){//到最后一位,说明所有合法
        		List<String> ls = new ArrayList<String>();
        		for(i = 0; i < al.size(); i++){
        			String s = "";//每一组的String
        			for(int j = 0; j < n;j++){
        				if(j == al.get(i)){
        					s += "Q";//放置皇后的位置
        				}
        				else{
        					s += ".";//不放的位置
        				}
        			}
        			ls.add(s);//加入到ls
        		}
        		returnList.add(ls);//加入一组解
        	}
        }
        return returnList;
    }
    /**
     * 推断是否合法
     * @param al 一组解
     * @param i 当前行
     * @param x 当前列
     * @return 是否合法
     */
    boolean check(List<Integer> al,int i,int x){
    	for(int k = 0; k < i; k++){//仅仅与上方比較,不然与会自身比較
    		if(al.get(k) == x || x - i == al.get(k) - k || x + i == al.get(k) + k)
    			return false;
    	}
		return true;
    }
    //求全排列
	public static List<List<Integer>> permuteUnique(int[] num) {
		List<List<Integer>> returnList = new ArrayList<List<Integer>>();
		returnList.add(new ArrayList<Integer>());

		for (int i = 0; i < num.length; i++) {
			Set<List<Integer>> currentSet = new HashSet<List<Integer>>();
			for (List<Integer> l : returnList) {
				for (int j = 0; j < l.size() + 1; j++) {
					l.add(j, num[i]);
					List<Integer> T = new ArrayList<Integer>(l);
					l.remove(j);
					currentSet.add(T);
				}
			}
			returnList = new ArrayList<List<Integer>>(currentSet);
		}

		return returnList;
	}
}

还有一种思路是回溯法,符合要求的往下走。不符合要求的往回退。

详细代码:

public class Solution {
    /**
     * 这题的总体思想是建一个x[n]的数组,意为第i放第x[i]列放置皇后
     * 皇后的合法推断规则是列不相等,斜线上也不相等
     * i + x[i] == j + x[j] 表示正斜线一致
     * x[i] - i = x[j] - j 表示负斜线上一致  都不合法
     */
	List<List<String>> list;//保存结果
	public List<List<String>> solveNQueens(int n) {
		list = new  ArrayList<List<String>>();
		int[] x = new int[n];//保存结果
		queens(x, n, 0);
		return list;
	}

	void queens(int[] x,int n,int row){
		for(int i = 0; i < n; i++){
			if(check(x,n,row,i)){//推断合法
				x[row] = i;//将皇后放在第row行,第i列
				if(row == n-1){//假设是最后一行,则输出结果
					addList(x,n);
					x[row] = 0;//回溯,寻找下一个结果
					return;
				}
				queens(x, n, row+1);//寻找下一行
				x[row] = 0;//回溯
			}
		}
	}

	/**
	 * 将每一组的结果加入list
	 * @param x 数组解
	 * @param n 棋盘长宽
	 */
	private void addList(int[] x,int n) {
		//加入结果
		String[][] sArr = new String[n][n];
		List<String> al = new ArrayList<String>();
		for(int i = 0; i < n ; i++){
			Arrays.fill(sArr[i], ".");//先填充.
			sArr[i][x[i]] = "Q";//特定位置放置Q
			String s = "";
			for(String str:sArr[i]){
				s += str;//加在一起
			}
			al.add(s);//加入一行
		}
		list.add(al);//加入一组解
	}

	/**
	 * @param x 数组解
	 * @param n 棋盘长宽
	 * @param index 当前放置行
	 * @param i 当前放置列
	 * @return
	 */
	boolean check(int[] x,int n,int row, int col){
		for(int i = 0; i < row; i++){
		    //由于行不相等,推断列是否相等。斜线上是否相等
			if(x[i] == col || x[i] + i == col + row || x[i] - i == col - row)
				return false;
		}
		return true;
	}
}
时间: 2024-10-27 04:42:09

leetCode 51.N-Queens (n皇后问题) 解题思路和方法的相关文章

leetCode 36.Valid Sudoku(有效的数独) 解题思路和方法

Valid Sudoku Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be partially filled, where empty cells are filled with the character '.'. A partially filled sudoku which is valid. Note: A valid Sudoku boa

leetCode 47.Permutations II (排列组合II) 解题思路和方法

Permutations II Given a collection of numbers that might contain duplicates, return all possible unique permutations. For example, [1,1,2] have the following unique permutations: [1,1,2], [1,2,1], and [2,1,1]. 思路:这题相比于上一题,是去除了反复项. 代码上与上题略有区别.详细代码例如以下

leetCode 35.Search Insert Position (搜索插入位置) 解题思路和方法

Search Insert Position Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. You may assume no duplicates in the array. Here are few examples. [1,3,5

leetCode 64.Minimum Path Sum (最短路) 解题思路和方法

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or right at any point in time. 思路:此题和前面几个机器人的题非常相像,只是变化了一点,具体代码和

leetCode 20.Valid Parentheses (有效的括号) 解题思路和方法

Valid Parentheses Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" a

leetCode 45.Jump Game II (跳跃游戏) 解题思路和方法

Jump Game II Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Your goal is to reach the last index in the minimum nu

leetCode 34.Search for a Range (搜索范围) 解题思路和方法

Search for a Range Given a sorted array of integers, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of O(log n). If the target is not found in the array, return [-1, -1]. For ex

leetCode 103.Binary Tree Zigzag Level Order Traversal (二叉树Z字形水平序) 解题思路和方法

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). For example: Given binary tree {3,9,20,#,#,15,7}, 3 / 9 20 / 15 7 return its zig

leetCode 42.Trapping Rain Water(凹槽的雨水) 解题思路和方法

Trapping Rain Water Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. For example, Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6. The above elevation map