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

    Problem:

    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:

    This is a very very typical DFS and back tracking problem!!!
    But for this specific problem, we could sovle it with a magic skill, which could greatly save the space complexity and time complexity. 
    Typical thinking:
    During the search process, we try to place a queen onto a position(i, j), then we check this placement againt all other placements, so as to make sure ethe current placement is valid.
    The instant idea for this is "check the new placement againt all girds before it". Since the borad is a "n*n" matrix, we have to use O(n^2) time complexity of checking a single placement. 
    
    But this problem could be elegantly solved by following observation:
    Since we only have one queue at each row, why not we just record each row's queen's column index? Why should we care about the empty space, since we actually never use them. 
    
    Great!!!! Haha!
    Step 1: compress the sparse matrix into an array.
    int[] placed = new int[n];
    Note: placed[i] denotes the there is queue at (i, placed[i]).
    
    Step 2: define a proper base case! At here, only when a path is valid, we allow it to go deeper! Thus we don't need to worry if the placement is legal when we just reach the next level. (We just need to use typical pos to check iff we have already place all queens properly)
    ----------------------------------------------------
    if (pos == n) {
        List<String> item = new ArrayList<String> ();
        for (int i = 0; i < n; i++) {
            String row = "";
            for (int j = 0; j < n; j++) {
                if (placed[i] != j)
                    row += ".";
                else
                    row += "Q";
            }
            item.add(row);
        }
        ret.add(item);
    }
    Note: the result recover process is very very interesting~~~Powerful~~~haha!
    
    Step 3:
    How to check if a placement is valid?
    We check the current placement against all previous placement(only queens)
    for (int i = 0; i < row_no; i++) {
        if (col_no == placed[i] || (Math.abs(col_no - placed[i]) == row_no - i))
            return false;
    } 
    
    Note: Since we use an array of recording our placement information, we do not need to recover the state (for other placements at the same level)
    for (int j = 0; j < n; j++) {
        if (isValid(placed, pos, j)) {
            placed[pos] = j; //other placement would automatically override placed[pos]
            helper(placed, n, pos+1, ret);
        }
    }
    But if we use arraylist, we need to do
    state.add(i);
    ...
    state.remove(state.size()-1);

    Solution:

    public class Solution {
        public List<List<String>> solveNQueens(int n) {
            List<List<String>> ret = new ArrayList<List<String>> ();
            if (n <= 0)
                return ret;
            int[] placed = new int[n];
            helper(placed, n, 0, ret);
            return ret;
        }
        
        
        private void helper(int[] placed, int n, int pos, List<List<String>> ret) {
            if (pos == n) {
                List<String> item = new ArrayList<String> ();
                for (int i = 0; i < n; i++) {
                    String row = "";
                    for (int j = 0; j < n; j++) {
                        if (placed[i] != j)
                            row += ".";
                        else
                            row += "Q";
                    }
                    item.add(row);
                }
                ret.add(item);
            }
            for (int j = 0; j < n; j++) {
                if (isValid(placed, pos, j)) {
                    placed[pos] = j;
                    helper(placed, n, pos+1, ret);
                }
            }
        }
        
        
        private boolean isValid(int[] placed, int row_no, int col_no) {
            for (int i = 0; i < row_no; i++) {
                if (col_no == placed[i] || (Math.abs(col_no - placed[i]) == row_no - i))
                    return false;
            }   
            return true;
        }
    }
  • 相关阅读:
    添加脚本真机调试Error launching remote program: failed to get the task for process xxx.
    问题资源Android lint 能够做的事情
    调用生成通过存储过程自动生成AWR报告
    破解行Android apk 逆向工程研究﹣破解 MyTV HD 機種限制手記
    代码判断判断给定的图是否是有向无环图
    修改系统android2.3.4增加gsensor
    类对象工厂设计模式(Factory Pattern)
    脚本指令《游戏脚本的设计与开发》第一章 读取和解析一个脚本文件
    级别指示Android Hierarchy 工具的一些知识
    nullnull[小代码] 双击BACK键 退出
  • 原文地址:https://www.cnblogs.com/airwindow/p/4851863.html
Copyright © 2011-2022 走看看