LeetCode-0608

51. N 皇后(困难)

思路:维护 列,对角线,反对角线的元素标记,之后按行的顺序去搜索,保证行序递增避免重复

优化:不使用数组维护,因为一行只能有一个皇后,那么可以直接记录每行皇后的位置,判断皇后位置的一维数组即可判断是否重复。

class Solution {

    List<List<String>> res;
    boolean[] column;
    boolean[] diagonal;
    boolean[] rediagonal;

    public List<List<String>> solveNQueens(int n) {
        
        res = new ArrayList<>();
        if(n==0)return res;

        List<List<Integer>> ans = new ArrayList<>();
        column = new boolean[n+1];
        diagonal = new boolean[2*n];
        rediagonal = new boolean[2*n];

        dfs(n,ans,1);

        return res;
    }


    public void dfs(int n,List<List<Integer>> ans,int row){
        if(row==n+1 && ans.size()==n){

            List<String> cur = new ArrayList<>(n);
            for(int i=0;i<n;i++)cur.add("");

            for(List<Integer> item:ans){
                int it = item.get(0);
                int jt = item.get(1);

                String tp = "";
                for(int i=1;i<=n;i++){
                    if(i==jt)tp+="Q";
                    else tp+=".";
                }
                cur.set(it-1,tp);
            }
            res.add(new ArrayList<>(cur));
            return;
        }

        for(int j=1,i=row;j<=n;j++){
            
            if(column[j] || diagonal[n-i+j] || rediagonal[i+j-1])continue;
            
            List<Integer> tp = new ArrayList<>();
                
            tp.add(i);
            tp.add(j);
            ans.add(tp);
            column[j] = true;
            diagonal[n-i+j] = true;
            rediagonal[i+j-1] = true;
            
            dfs(n,ans,i+1);

            ans.remove(ans.size()-1);
            column[j] = false;
            diagonal[n-i+j] = false;
            rediagonal[i+j-1] = false;
        }
    }
}
//	优化后:
class Solution {

    public List<List<String>> solveNQueens(int n) {

        List<List<String>> res = new ArrayList<>();
        int[] queen = new int[n];
        Arrays.fill(queen,-1);
        dfs(queen,res,0,n);
        return res;
    }

    public void dfs(int[] queen, List<List<String>> res,int row,int n){
        if(row == n){
            List<String> solution = new ArrayList<>();
            for(int i=0;i<n;i++){
                StringBuilder sb = new StringBuilder();
                for (int j = 0; j < n; j++) {
                    sb.append(queen[i] == j ? 'Q' : '.');
                }
                solution.add(sb.toString());
            }
            res.add(solution);
            return ;
        }

        for(int j=0;j<n;j++){
            if(isValid(queen,row,j)){
                queen[row] = j;
                dfs(queen,res,row+1,n);
                queen[row] = -1;
            }
        }

    }


    public boolean isValid(int[] queen,int row,int col){

        for(int i=0;i<row;i++){
            int j = queen[i];
            if(j == col || row - i == Math.abs(col - j))return false; 
        }
        return true;
    }

}

前者4ms,优化后2ms, 通过消融实验发现,真正优化时间的在于使用StringBuilder和在solution.add的时候,不使用new对象加入。

你可能感兴趣的:(LeetCode,leetcode,深度优先,算法)