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;
        }
    }
  • 相关阅读:
    短信平台接口调用方法参考
    C#部分类与部分方法
    Oracle表字段类型更改的一个经验
    ueditor的上传文件漏洞(c#)
    判断一个文件是否是指定后缀名的文件
    利用FluorineFx的ByteArray上传图片
    FluorineFx 播放FLV 时堆棧溢出解决 FluorineFx NetStream.play 并发时,无法全部连接成功的解决办法
    Flex数据交互之Remoting[转]
    fluorinefx使用手册
    SharedObject使用:在FluorineFx.net与Flex中使用共享对象维护在线用户列表实例【转】
  • 原文地址:https://www.cnblogs.com/airwindow/p/4747141.html
Copyright © 2011-2022 走看看