[leet code] N-Queens & II

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.."]
]
============

Analysis:

Basic idea of which is to try all the possible queen location combinations, add the valid ones in to result set and ignore the invalid ones.

Therefore, the problem can be divided into 3 components:

1. Go through all possible queen location combination.

2. Check if a combination is valid.

3. Form the result.


Rules of our problem:

1. Queens can not be in the same row

2. Queens can not be in the same column

3. Queens can not be in the diagonal


According to rule 1 (each row would exist only 1 queen), we can create a 1D array to hold a possible queen location combination.  The Indexes of the array elements represent the row numbers, while the values of the array elements present the location of the queens. Take 4-queens puzzle for example, solution 1 can be represented by array[1, 3, 0, 2]; solution 2 can be represented by array[2, 0, 3, 1].

To fulfill the rule 2, we initiate the values of the newly created array from 0 to n-1, so that non of the queen would be in the same column.

Therefore, going through all the possible queen location combinations becomes problem of going through all the possible combinations of array elements. Take 3-queens puzzle for example, possible array element combination can be [0,1,2], [0,2,1], [1,0,2], [1,2,0], [2,0,1], [2,1,0].

Here is an algorithm to solve this problem:

Case of only 1 element: [0]

Case of 2 elements: [0, 1] [1, 0]

Case of 3 elements: [2,0,1] [2,1,0] [0,2,1] [0,1,2] [1,0,2] [1,2,0]


Process of case 3 can be demonstrated as:

1. Fix 2 as the first element and find all possible combinations of remaining elements (0,1), then append 3 to each of the possible combination. ([2,0,1] [2,1,0])

2. Fix 0 as the first element and find all possible combinations of remaining elements (1,2), then append 0 to each of the possible combination. ([0,2,1] [0,1,2])

3. Fix 1 as the first element and find all possible combinations of remaining elements (0,2), then append 0 to each of the possible combination. ([1,0,2] [1,2,0])

From step 1 to step 2,  we can switch the value of 2 and 0.  While from step 2 to step 3, we can 1st fall back step 2 to step 1, then switch the value of 2 and 1.


To generalize the logic above, we can first fix the first element of the array, then calculate all the possible combination of the remaining (n-1) elements (recursive call) and append each combination to the first element.  <- one complete possible element combination.  

After that, we can switch the first element with other elements one by one and repeat the process above to get all the possible element combinations.


Finally, rule 3 can be implemented by comparing (row of queen 1 - row of queen 2) == (column of queen 1 - column of queen 2) ||  (row of queen 1 - row of queen 2) == (column of queen 2 - column of queen 1).

public class Solution {
    public static ArrayList<String[]> solveNQueens(int n) {
        ArrayList<String[]> rs = new ArrayList<String[]>();
        
        if(n<1) return rs;
        
        /*column index array, in which index of an element prepresents row number, value of an element presents location of 
        queen*/ 
        int[] columnIndex = new int[n];
        for(int i=0; i<n; i++) {
        	columnIndex[i] = i; // ensure queens in different row would be in different column
        }
        helper(columnIndex, n, 0, rs);
        return rs;
    }
    
	public static void helper(int[] columnIndex, int length, int index, ArrayList<String[]> rs) {
		if (index == length) {

			if (isValid(columnIndex)) formResult(columnIndex, rs);
		} else {
			for (int i = index; i < length; i++) {
				int temp = columnIndex[i];
				columnIndex[i] = columnIndex[index];
				columnIndex[index] = temp;

				helper(columnIndex, length, index + 1, rs);

				columnIndex[index] = columnIndex[i];
				columnIndex[i] = temp;
			}
		}
	}
    
    public static boolean isValid(int[] columnIndex){
        for(int i=0; i<columnIndex.length-1; i++){
            for(int j=i+1; j<columnIndex.length; j++){
                if(i-j==columnIndex[i]-columnIndex[j] || i-j==columnIndex[j]-columnIndex[i]) return false;
            }
        }
        return true;
    }
    
    public static void formResult(int[] columnIndex, ArrayList<String[]> rs){
        String[] singleResult = new String[columnIndex.length];
        for(int i=0; i<columnIndex.length; i++){// for each row
            StringBuffer temp = new StringBuffer();
            for(int j=0; j<columnIndex.length; j++){// for each column
                if(j == columnIndex[i]) temp.append("Q");
                else temp.append(".");
            }
            singleResult[i]=temp.toString();
        }
        rs.add(singleResult);

    }
}

N-Queens II

Follow up for N-Queens problem.

Now, instead outputting board configurations, return the total number of distinct solutions.

============

Analysis:

Similar to the N-Queens approach, change only the formResult component.

public class Solution {
    static int rs;
    public int totalNQueens(int n) {
        if(n<1) return 0;
        rs = 0;
        int[] columnIndex = new int[n];
        for(int i=0; i<n; i++) columnIndex[i] = i; // initiate queen locations
        helper(columnIndex, 0);
        return rs;
    }
    
    public void helper(int[] columnIndex, int index){
        if(index == columnIndex.length) {
            if(isValid(columnIndex)) {
                rs++;
            }
        } else{
            for(int i=index; i<columnIndex.length; i++){
                int temp = columnIndex[index];
                columnIndex[index] = columnIndex[i];
                columnIndex[i] = temp;
                
                helper(columnIndex, index+1);
                
                columnIndex[i] = columnIndex[index];
                columnIndex[index] = temp;
            }
        }
    }
    
    public boolean isValid(int[] columnIndex){
        for(int i=0; i<columnIndex.length-1; i++){
            for(int j=i+1; j<columnIndex.length; j++){
                if(i-j==columnIndex[i]-columnIndex[j]||i-j==columnIndex[j]-columnIndex[i]) return false;
            }
        }
        return true;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值