带你轻松拿捏N皇后问题

简介: 要求任何两个皇后不同行、不同列,也不在同一 条斜线上

image.png


第一题:只求摆法有多少种


N皇后问题是指在N*N的棋盘上要摆N个皇后,


要求任何两个皇后不同行、不同列,也不在同一 条斜线上


给定一个整数 n,返回 n 皇后的摆法有多少种。


n=1,返回1


n=2或3,2皇后和3皇后问题无论怎么摆都不行,返回0


n=8,返回 92


public static int num(int n) {
    if (n < 1) return 0;
    int[] record = new int[n];  // 用于记录下过的地方, record[x] = y 表示在 x 行时下的是第 y 列
    return process(record, 0);
}
/**
 * @param record  之前下过的位置
 * @param x  当前来到 x 行
 * @return
 */
public static int process(int[] record, int x) {
    if (x == record.length) return 1;  // 如果 n 个皇后都走完,那么说明找到了一种方法
    int res = 0;
    //尝试把 x 行的皇后放到 y 列
    for (int y = 0; y < record.length; y++) {
        if (isVaild(record, x, y)) {
            record[x] = y;
            res += process(record, x + 1);
        }
    }
    return res;
}
/**
 * @param record
 * @param x 当前所在行
 * @param y 当前所在列
 * @return
 */
public static boolean isVaild(int[] record, int x, int y) {
    for (int i = 0; i < x; i++) {
        // 如果与之前摆过的皇后在同一列 || 在同一斜线上
        if (record[i] == y || Math.abs(i - x) == Math.abs(record[i] - y)) {
            return false;
        }
    }
    return true;
}


上面这题看着我的注释是非常好理解的,如果还是不理解,可以将4传入,通过调试的方式跟着代码走一遍那就会很清楚了。


第二题


这题相比于上题变化不大,就是不要结果有多少种,而是返回一个 List<List>


其中里面的 List 存了其中一种摆法,例如:


image.png


用:'Q''.' 分别代表了皇后和空位


因为在上一题中我们是有记录 成功摆完所有皇后时皇后位置的,所以我们只要把之前记录代码的地方给去掉 并且把 record 转换为需要的结果那样表达就行了


LinkedList<List<String>> ans = new LinkedList<>();
public List<List<String>> solveNQueens(int n) {
    if (n < 1) return null;
    int[] record = new int[n];
    process(record, 0);
    return ans;
}
public void process(int[] record, int x) {
    if (x == record.length) {
        //对皇后摆放的位置处理为题目要的结果
        handleResult(record);
        return;
    }
    for (int y = 0; y < record.length; y++) {
        if (isVaild(record, x, y)) {
            record[x] = y;
            process(record, x + 1);
        }
    }
}
public boolean isVaild(int[] record, int x, int y) {
    for (int i = 0; i < x; i++) {
        if (record[i] == y || Math.abs(i - x) == Math.abs(record[i] - y)) {
            return false;
        }
    }
    return true;
}
public void handleResult(int[] record) {
    ArrayList<String> list = new ArrayList<>();
    StringBuilder builder = new StringBuilder();
    int row = record.length;  // 行数和列数都为record.length
    int col = record.length;  // 这里分开写只是为了方便理解就用两参数表示
    for (int i = 0; i < col; i++) { //先把棋盘中一行的内容全设为 “.”
        builder.append(".");
    }
    for (int i = 0; i < row; i++) {  // 通过 record 把每行皇后对应位置设置为 "Q"
        StringBuilder tmp = new StringBuilder(builder);
        tmp.replace(record[i], record[i] + 1, "Q");
        list.add(tmp.toString());
    }
    ans.add(list);
}


力扣题目链接:


第一题:leetcode.cn/problems/n-…

第二题:leetcode.cn/problems/n-…

目录
相关文章
|
1月前
|
存储 算法
|
6月前
【随想】每日两题Day.3(实则一题)
【随想】每日两题Day.3
29 0
|
6月前
|
存储
【随想】每日两题Day.10(实则一题)
【随想】每日两题Day.10(实则一题)
33 0
|
6月前
|
存储 算法
【随想】每日两题Day.20(实则一题)
【随想】每日两题Day.20(实则一题)
35 0
|
6月前
【随想】每日两题Day.16(实则一题)
【随想】每日两题Day.16(实则一题)
35 0
|
6月前
【随想】每日两题Day.5 (实则一题)
【随想】每日两题Day.5
30 0
|
6月前
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
41 0
|
算法
【过河卒】回溯算法保姆式解题
【过河卒】回溯算法保姆式解题
95 0
|
存储
剑指Offer - 面试题14:剪绳子
剑指Offer - 面试题14:剪绳子
83 0
|
机器学习/深度学习
剑指offer 13. 剪绳子
剑指offer 13. 剪绳子
73 0