51. N-Queens

题意:n-皇后问题,即将n个皇后放到n*n的棋盘上满足任意两个皇后都不能攻击彼此,皇后一步能攻击其他同行、同列或者同对角线的皇后

要求:输入维度整数n,返回n皇后问题的所有不同的方案,每种方案是不同的放置布局,其中‘Q’和‘.’分别表示皇后和 空白空间。

思路:1、从结果来看,每列只有一个皇后,每行只有一个皇后。选择从行考虑(或者从列考虑,由对称性知,会得到相同的结果),使用的数据结构stack。

            2、如何判断后面的位置能否放置皇后?1 每次放置一个皇后,根据其位置将后面不能放置的位置放到哈希表(排除的位置表)中。

           3、如何判断不能放置的位置,即同行、同列、同对角线?采用ax+by+c=0。具体的,x=x0,y=y0,y=+-x + c0

public class Solution {
  public List
  
  
   
   
    
    > solveNQueens(int n) {
        List
    
    
     
     
      
      > solToString = new LinkedList<>();
        List
      
       
       
         > sols = new LinkedList<>(); ArrayList 
        
          path = new ArrayList<>(n); nQueensComplete(sols, path, n, 0); // addNQueens(sols, path, n, 0); solsToStr(sols, solToString, n); return solToString; } private void nQueensComplete(List 
          
          
            > sols, ArrayList 
           
             path, int n, int i) { addNQueens(sols, path, n, 0); mirrored(sols, n); } private void mirrored(List 
             
             
               > sols, int n){ LinkedList 
               
               
                 > mirrorSols = new LinkedList<>(); for(List 
                
                  sol : sols){ ArrayList 
                 
                   mirror = new ArrayList<>(n); Coordinate queen = sol.get(0); //首行的元素 if(n % 2 == 1 && queen.y == (n-1)/2){ //正中间的处理,避免重复 continue; } mirror.add(new Coordinate(queen.x, (n-1)-queen.y)); for(int i = 1; i < sol.size(); i++){ queen = sol.get(i); Coordinate mirQueen = new Coordinate(queen.x, (n-1)-queen.y); mirror.add(mirQueen); } mirrorSols.addFirst(mirror); } sols.addAll(mirrorSols); } private void solsToStr(List 
                   
                   
                     > sols, List 
                     
                     
                       > solToString, int n) { for(List 
                      
                        sol : sols){ ArrayList 
                       
                         nQueenToStr = new ArrayList<>(n); for(Coordinate queen : sol){//按行存 String s = ""; for(int col = 0; col < n; col++){ if(col != queen.y){ s += "."; }else{ s += "Q"; } } nQueenToStr.add(s); } solToString.add(nQueenToStr); } } private void addNQueens(List 
                         
                         
                           > sols, ArrayList 
                          
                            path, int n, int startRow) { for(int col = 0; col < n; col++){ if(startRow == 0 && col >= (n+1)/2)//根据对称性将搜索减半 return; Coordinate startPoint = new Coordinate(startRow, col); for(int i = path.size()-1; i >= startRow; i--){ path.remove(i); } if(!testPoint(path, startPoint)) continue; path.add(startPoint); if(startRow == (n-1)){ sols.add(new ArrayList<>(path)); return; } addNQueens(sols, path, n, startRow+1); } } private boolean testPoint(ArrayList 
                           
                             path, Coordinate startPoint) { for(Coordinate queen : path){ if(queen.x == startPoint.x || queen.y == startPoint.y){ return false; } if(startPoint.y - queen.y == startPoint.x - queen.x) //k=1 return false; if(startPoint.y - queen.y == queen.x - startPoint.x) return false; } return true; } public static class Coordinate{ int x; int y; public Coordinate(int x, int y) { super(); this.x = x; this.y = y; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Coordinate other = (Coordinate) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } } } 
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
      
     
     
    
    
   
   
  
  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值