zoukankan      html  css  js  c++  java
  • [LeetCode#52]N-Queens II

    Problem:

    Follow up for N-Queens problem.

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

    link:

    https://leetcode.com/problems/n-queens-ii/

    Analysis:

    Prolem definition:
    https://en.wikipedia.org/wiki/Eight_queens_puzzle
    --------------------------------------------------------------------------------------
    solution 1: (Wrong solution, no two queens could be placed on the same diagonal line.)
        public int totalNQueens(int n) {
            if (n <= 0)
                return 0;
            ArrayList<Integer> ret = new ArrayList<Integer> ();
            ret.add(0);
            boolean[] used_column = new boolean[n];
            for (int j = 0; j < n; j++) {
                helper(used_column, n, 0, j, ret);
            }
            return ret.get(0);
        }
    
        private void helper(boolean[] used_column, int n, int i, int j, ArrayList<Integer> ret) {
            if (i == n - 1 && used_column[j] == false) {
                ret.set(0, ret.get(0) + 1);
                return;
            }
            if (used_column[j]) {
                return;
            } else{
                used_column[j] = true;
                for (int next_column = 0; next_column < n; next_column ++) {
                    helper(used_column, n, i + 1, next_column, ret);
                }
                used_column[j] = false;
            }
        }
        
        
    At first glance, it seems we have to use a two dimensional array to record each queen's position, since we need to check there are two queens on the same diagonal. However, there is a very important skill in solving this problem: each row would only taken up a single queen. 
    Here, we introduce a more elegant and powerful solution for this problem.
    Basic idea:
    We check each new placement against the post placement, it is valid we continue to place on the next row. (the same idea as above solution). However could significantly alleviate the coding work, by use inherently backtracking. 
    At above solution, 
    helper(boolean[] used_column, int n, int i, int j, ArrayList<Integer> ret)
    ------------------------------------------------------------------------
    we specify the column number j for the row i. The incovenience for this method is that we need obviously recover the used_column's state before we specify the column number j+1.
    This design introduce the following code snippt.
    ------------------------------------------------------------
    used_column[j] = true;
    for (int next_column = 0; next_column < n; next_column ++) {
        helper(used_column, n, i + 1, next_column, ret);
    }
    used_column[j] = false; (for back tracking purpose)
    
    Also introduce following ugly code snippt when invoking helper.
    for (int j = 0; j < n; j++) {
        helper(used_column, n, 0, j, ret);
    }
    
    The above way is too ugly for this probelm. We could take advantage of "for-loop" over the same element, so as to avoid obviously backtracking.
    helper(int row, int n, int[] column_for_row, ArrayList<Integer> ret)
    At each helper, we test against each column placement for a row. 
    for (int i = 0; i < n; i++) {
        column_for_row[row] = i;
        if (isValid(row, column_for_row))
            helper(row + 1, n, column_for_row, ret);
    }
    Even the current placement is not valid, the for loop could easily take us for the next column placement by overwriting the column_for_row[row] into i+1.
    
    Skills:
    1. use the exceed case as base case. 
    Since at each helper, we firstly check if the current placement is valid, and then go to the next row. If we reach the row n, it means the rows before n-1 are all valid.
    if (row == n) {
        ret.set(0, ret.get(0) + 1);
        return;
    }
    
    2. use the column_for_row to check agianst vioation cases.
    ------------------------------------------------------------
    2.1 two queens were placed in the same column.
    if (column_for_row[i] == column_for_row[row])
    
    2.2 two queens on the same diagonal line. 
    if ((row - i) == Math.abs(column_for_row[row] - column_for_row[i]))
    Note: must use abs, not sure which placement is at the lower column.
    
    
    Time complexity:
    Even though this question only ask for the total count. We still have to search along all possible routines.
    At each row, we could place a queen on any column. (at least we have tested for each placement)
    Thus the time complexity is sadly O(n^2)

    Solution:

    public class Solution {
        public int totalNQueens(int n) {
            if (n <= 0)
                return 0;
            ArrayList<Integer> ret = new ArrayList<Integer> ();
            ret.add(0);
            int[] column_for_row = new int[n];
            helper(0, n, column_for_row, ret);
            return ret.get(0);
        }
        
        private void helper(int row, int n, int[] column_for_row, ArrayList<Integer> ret) {
            if (row == n) {
                ret.set(0, ret.get(0) + 1);
                return;
            }
            //a totally different way of thinking!!!!
            for (int i = 0; i < n; i++) {
                column_for_row[row] = i;
                if (isValid(row, column_for_row))
                    helper(row + 1, n, column_for_row, ret);
            }
        }
        
        private boolean isValid(int row, int[] column_for_row) {
            for (int i = 0; i < row; i++) {
                if (column_for_row[i] == column_for_row[row] || (row - i) == Math.abs(column_for_row[row] - column_for_row[i]))
                    return false;
            }   
            return true;
        }
    }
  • 相关阅读:
    Spring中的Bean的配置形式
    使用外部属性文件配置Bean以及Bean的生命周期方法
    运行时找到main方法所在的类
    获取SpringMVC中所有RequestMapping映射URL信息
    RequestBody只能读取一次的问题
    接口标记为@ResponseBody却不进入ResponseBodyAdvice
    springboot打成jar包后无法解压
    Springboot打包执行源码解析
    关于base64的一个小细节
    Liquibase使用入门
  • 原文地址:https://www.cnblogs.com/airwindow/p/4747141.html
Copyright © 2011-2022 走看看