算法 52

76 阅读1分钟

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

[原题链接]leetcode-cn.com/problems/n-…

思路: 打算采用回溯来做,因为在回溯的典型题目是8皇后,所以这里也采用回溯来做。 假设a[i][j]代表棋盘的一个点位,假设占据其中一点,那么有如下几个公式可以推到

  • a[i][0-n] 不可被其他皇后占用
  • a[0-n][j] 不可被其他皇后占用
  • 任意一点b[s][m] 当s+m = i+j,时,这个点位在a皇后的线上
  • 任意一点b[s][m] 当s-m = i-j,时,这个点位在a皇后的线上
class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> allList = new ArrayList();
        // 层数
        int i=0;
        // 不能选的i
        Set<Integer> seti = new  HashSet();
         // 不能选的j
        Set<Integer> setj = new  HashSet();
          // 不能选的和
        Set<Integer> setSum = new HashSet();
        // 不能选的差
        Set<Integer> setCum = new HashSet();

        Map<Integer,String> k = new HashMap();
        String  result = "";
        helper(allList,n,i,seti,setj,setSum,setCum,k);
        return allList;

    }

    /***
     **/
    public void helper(List<List<String>> allList,int n,int i,
                       Set<Integer> seti,Set<Integer> setj,Set<Integer> setSum, Set<Integer> setCum,Map<Integer,String> k){
        if(i == n){
            // 平装返回的数据
            List<String> templist = new ArrayList();
            for(Integer key:k.keySet()){
                if(key != n){
                    String v = k.get(key);
                        while(v.length() < n){
                            v = v+".";
                        }
                    templist.add(v);
                }

            }
            k = new HashMap();
            allList.add(templist);
        }
        k.put(i,"");
        // 每一列都遍历
        for(int r=0;r < n;r++){
            if(check(i,r,seti,setj,setSum,setCum)){
                String row =  k.get(i);
                k.put(i,row + "Q");
                // 禁止 i 行
                seti.add(i);
                // 禁止 j 行
                setj.add(r);
                // 禁止斜线
                setSum.add(i-r);
                setCum.add(r+i);
                helper(allList,n,i+1,seti,setj,setSum,setCum,k);
                // 还原 i 行
                seti.remove(i);
                // 还原 j 行
                setj.remove(r);
                setSum.remove(i-r);
                setCum.remove(r+i);
                if(k.containsKey(i)){
                    k.put(i,row + ".");
                }else{
                    k.put(i,"");
                }
            }else{
                String row =  k.get(i) + ".";
                k.put(i,row);
                continue;
            }
        }
        k.putIfAbsent(i,"");
    }
	// 校验i,j 是否可以容下一个皇后
    public boolean check(int i,int j,
                         Set<Integer> seti,Set<Integer> setj,Set<Integer> setSum,Set<Integer> setCum){
        if(seti.contains(i)){
            return false;
        }
        if(setj.contains(j)){
            return false;
        }
        if(setSum.contains(i-j)){
            return false;
        }
        if(setCum.contains(i+j)){
            return false;
        }
        return true;
    }


}

能过,但是时间和效率不够好,在评论区有很多优秀的方案,可以一起去看。