leetcode 51 N皇后问题

经典的回溯算法问题

我们需要想清楚2点

  1. 需要使用回溯算法
  2. 如何判断两个皇后是否可以相互攻击

回溯算法就不需要多说了。判断2个皇后是否可以相互攻击,主要看是否是同一行,同一列,或者同一对角线的。我们可以开额外的空间存储存储同列的,同行的,同对角线的坐标,同对角线的怎么把他们用一个确定的数字表示呢?我们可以把他们分为2类

  1. 从右下角到左上角,也就是斜率为-1
    这条线上的坐标均有 x+y = k(常数),k为直线与y轴的截距
  2. 从左下角到右上角也就是斜率为1
    这条线上的坐标均有 x-y = k,k为直线与x轴的截距

code:

package undone;

import com.sun.rowset.internal.Row;

import  java.util.*;

/**
 * @desc
 * 经典回溯算法:n皇后问题
 */
public class t51 {
    class Position {
        Position(int x, int y) {
            this.x = x;
            this.y = y;
        }
        int x;
        int y;
    }

    List<List<Position>>  posList = null;
    Set<Integer> RowSet = new HashSet<>();
    Set<Integer> ColSet = new HashSet<>();
    Set<Integer> AsLeft = new HashSet<>();
    Set<Integer> AsRight = new HashSet<>();


    public List<List<String>> solveNQueens(int n) {
        if(n == 0) {
            return new ArrayList<>();
        }
        posList = new ArrayList<>();
        solveNQueens(new ArrayList(), 0, n);
        return generatorResult(posList, n);
    }

    public void solveNQueens(List<Position> poses, int row,  int n) {

       if(n == poses.size()) {
           List<Position> list = new ArrayList();
           list.addAll(poses);
           posList.add(list);
       }
       for(int i = row; i < n; i++) {
           for (int j = 0; j < n; j++) {
               if(judge(i, j)) {
                   poses.add(new Position(i, j));
                   RowSet.add(i);
                   ColSet.add(j);
                   AsLeft.add(i+j);
                   AsRight.add(i-j);
                   solveNQueens(poses, i+1,  n);
                   poses.remove(poses.remove(poses.size() - 1));
                   RowSet.remove(i);
                   ColSet.remove(j);
                   AsLeft.remove(i+j);
                   AsRight.remove(i-j);
               }
           }
       }

    }

    public String getString(int j, int n) {
        char[] cs = new char[n];
        for(int i = 0; i < n; i++) {
            if(i == j) {
                cs[i] = 'Q';
                continue;
            }
            cs[i] = '.';
        }
        return  new String(cs);
    }

    public List<List<String>> generatorResult(List<List<Position>> lists, int n) {
        List<List<String>>  result = new ArrayList<>();
        for (List<Position> list : lists) {
            List<String> item = new ArrayList<>();
            for (Position position : list) {
                item.add(getString(position.y, n));
            }
            result.add(item);
        }
        return result;
    }

    public boolean judge(int x0, int y0) {

        return !(RowSet.contains(x0) || ColSet.contains(y0) || AsLeft.contains(x0 + y0) || AsRight.contains(x0 - y0));
    }

    /**
     * Main方法
     * @param args
     */
    public static void main(String[] args) {
        t51 t51 = new t51();
        System.out.println(t51.solveNQueens(4));
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值