51/52. N-Queens -- 待优化

经典的八皇后问题,

queen 可以攻击的范围:  水平,垂直,斜向, 放置 queen 让所有的queens 不在对方的攻击范围内,问有多少种方法或者产生相应的棋盘。

分析: 依次产生每一行的结果, 先在某行某个位置放一个结果,如果不能产生解 则back tracking 到上一行,重新放置。

以 n=4 为例,每个位置都得分解 n=4 份, 算法复杂度为 n^n ,是一个很高的结果,因此当 n>12 时,测试用例都会TLE。 

需要解决的问题:

1. 如果存储 每个位置, 可以定义一个Node {int i, int j} 来标记index, 也可以 在二维矩阵中 用 i*n +j 来唯一的标志位置,只是每次需要 用除法和mod 来计算 i, j 。

给出一个代码, 但代码只排到 10%左右, 需要进一步优化:

class Solution {
    public List<List<String>> solveNQueens(int n) {
       List<List<Integer>> result = new ArrayList<>();
       dfs(new ArrayList<>(), result,0,n);
       return generate_results(result,n);
    }
    
    private List<List<String>> generate_results(List<List<Integer>> result,int n){
        StringBuilder init_str = new StringBuilder();
        for(int i=0; i<n; i++){
            init_str.append(".");
        }
        //System.out.println(init_str);
        
        List<List<String>> re_resu = new ArrayList<>();
        for(List<Integer> cur: result){
            List<String> cur_str = new ArrayList<>();
            for(int val: cur){
                int j = val%n;
                init_str.setCharAt(j,'Q');
                cur_str.add(init_str.toString());
                //System.out.println(cur_str);
                init_str.setCharAt(j,'.');
            }
            re_resu.add(new ArrayList<>(cur_str));
        }
        return re_resu;
    }
    
    private void dfs(List<Integer> curResult, List<List<Integer>> result, int rows,int n){
        if(curResult.size() == n){
            result.add(new ArrayList<>(curResult));
            //System.out.println(curResult);
            return ;
        }
        
        if(rows>=n) return;
        
        for(int i=0; i<n; i++){
            int candid = rows*n +i;
            if(isValid(curResult, candid,n)){
                curResult.add(candid);
                dfs(curResult,result,rows+1,n);
                curResult.remove(curResult.size()-1);
            }
        }
    }
    
    private boolean isValid(List<Integer> curResult, int candid, int n){
        int i = candid/n;
        int j = candid%n;
        
        // 水平 and 垂直
        for(int cur: curResult){
            int cur_i = cur/n;
            int cur_j = cur%n;
            if(i == cur_i || j== cur_j) return false;
        }
        
        int x = 0;
        //斜向:left up
        for(x =0; x<n; x++){
            if(i-x <0 || j-x<0) break;
            int left_up = (i-x)*n + (j-x);
            if(curResult.contains(left_up)) return false;
        }
        // right down
        for(x=0; x<n; x++){
            if(i+x>=n || j+x >=n) break;
            int right_down = (i+x)*n + j+x;
            if(curResult.contains(right_down)) return false;
        }
        
        //right up
        for(x=0; x<n; x++){
            if(i-x<0 || j+x>=n) break;
            int right_up = (i-x) *n +j+x;
            if(curResult.contains(right_up)) return false;
        }
        //left down
        for(x=0; x<n; x++){
            if(i+x>=n|| j-x<0) break;
            int left_down = (i+x)*n + j-x;
            if(curResult.contains(left_down)) return false;
        }
        return true;
    }
}

猜你喜欢

转载自www.cnblogs.com/keepAC/p/9973798.html