N皇后问题




/**
* 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
*/

N皇后第一版代码:性能较差,但是完全由自己写粗来的,基于此版本优化:

package com.javartisan.redpacket;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
 */
class Solution {

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

        List<List<String>> ans = new ArrayList<>();
        byte[][] mtx = new byte[n][n];
        ArrayList<String> an = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            an.add("");
        }
        trace(ans, an, n, n, mtx);
        HashSet<List<String>> set = new HashSet<>(ans);
        return new ArrayList<>(set);
    }

    public static void trace(List<List<String>> ans, ArrayList<String> an, int n, int cur, byte[][] mtx) {

        if (cur == 0) {
            ans.add((List<String>) an.clone());
            return;
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (check(mtx, i, j, n)) {
                    mtx[i][j] = 1;
                    StringBuilder sb = new StringBuilder();
                    for (int k = 0; k < n; k++) {
                        if (k == j) {
                            sb.append("Q");
                        } else {
                            sb.append(".");
                        }
                    }
                    an.set(i, sb.toString());
                    trace(ans, an, n, --cur, mtx);
                    an.set(i, "");
                    mtx[i][j] = 0;
                    cur++;
                }
            }
        }

    }


    public static boolean check(byte[][] mtx, int x, int y, int n) {

        boolean status = true;

        for (int i = 0; i < n && status; i++) {
            if (mtx[x][i] == 1) {
                status = false;
                break;
            }
        }

        for (int i = 0; i < n && status; i++) {
            if (mtx[i][y] == 1) {
                status = false;
                break;
            }
        }

        for (int i = x, j = y; i > 0 && j > 0 && status; i--, j--) {
            if (mtx[i - 1][j - 1] == 1) {
                status = false;
                break;
            }
        }

        for (int i = x, j = y; i < n - 1 && j < n - 1 && status; i++, j++) {

            if (mtx[i + 1][j + 1] == 1) {
                status = false;
                break;
            }
        }

        for (int i = x, j = y; i < n - 1 && j > 0 && status; i++, j--) {

            if (mtx[i + 1][j - 1] == 1) {
                status = false;
                break;
            }
        }

        for (int i = x, j = y; i > 0 && j < n - 1 && status; i--, j++) {

            if (mtx[i - 1][j + 1] == 1) {
                status = false;
                break;
            }
        }

        return status;
    }

    public static void main(String[] args) {

        byte[][] mtx = {
                {0, 0, 1, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0},
        };

        int n =7;
        long start = System.currentTimeMillis();
        System.out.println(solveNQueens(n));
        System.out.println(System.currentTimeMillis() - start);
        System.out.println(solveNQueens(n).size());

    }
}

简单优化版:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
 */
class Solution {


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

        byte[] x = new byte[n];
        byte[] y = new byte[n];

        List<List<String>> ans = new ArrayList<>();
        byte[][] mtx = new byte[n][n];
        ArrayList<String> an = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            an.add("");
        }
        trace(ans, an, n, n, mtx, x, y);
        HashSet<List<String>> set = new HashSet<>(ans);
        return new ArrayList<>(set);
    }

    public static void trace(List<List<String>> ans, ArrayList<String> an, int n, int cur, byte[][] mtx, byte[] usedX, byte[] usedY) {

        if (cur == 0) {
            ans.add((List<String>) an.clone());
            return;
        }
        for (int i = 0; i < n; i++) {
            if (usedX[i] == 1) {
                continue;
            }
            for (int j = 0; j < n; j++) {
                if (usedY[j] != 1 && check(mtx, i, j, n)) {
                    mtx[i][j] = 1;
                    usedX[i] = 1;
                    usedY[j] = 1;
                    StringBuilder sb = new StringBuilder();
                    for (int k = 0; k < n; k++) {
                        if (k == j) {
                            sb.append("Q");
                        } else {
                            sb.append(".");
                        }
                    }
                    an.set(i, sb.toString());
                    trace(ans, an, n, --cur, mtx, usedX, usedY);
                    an.set(i, "");
                    mtx[i][j] = 0;
                    usedX[i] = 0;
                    usedY[j] = 0;
                    cur++;
                }
            }
        }

    }


    public static boolean check(byte[][] mtx, int x, int y, int n) {

        boolean status = true;

        for (int i = 0; i < n && status; i++) {
            if (mtx[x][i] == 1) {
                status = false;
                break;
            }
        }

        for (int i = 0; i < n && status; i++) {
            if (mtx[i][y] == 1) {
                status = false;
                break;
            }
        }

        for (int i = x, j = y; i > 0 && j > 0 && status; i--, j--) {
            if (mtx[i - 1][j - 1] == 1) {
                status = false;
                break;
            }
        }

        for (int i = x, j = y; i < n - 1 && j < n - 1 && status; i++, j++) {

            if (mtx[i + 1][j + 1] == 1) {
                status = false;
                break;
            }
        }

        for (int i = x, j = y; i < n - 1 && j > 0 && status; i++, j--) {

            if (mtx[i + 1][j - 1] == 1) {
                status = false;
                break;
            }
        }

        for (int i = x, j = y; i > 0 && j < n - 1 && status; i--, j++) {

            if (mtx[i - 1][j + 1] == 1) {
                status = false;
                break;
            }
        }

        return status;
    }

    public static void main(String[] args) {

        byte[][] mtx = {
                {0, 0, 1, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0},
        };

        System.out.println(solveNQueens(4).size());


        int n = 7;
        long start = System.currentTimeMillis();
        System.out.println(solveNQueens(n));
        System.out.println(System.currentTimeMillis() - start);
        start = System.currentTimeMillis();
        System.out.println(solveNQueens(8).size());
        System.out.println(System.currentTimeMillis() - start);
    }
}

  

优化第三版:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
 */
class Solution {

    StringBuilder sb = null;
    byte[] mx = null;
    byte[] my = null;

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

        List<List<String>> ans = new ArrayList<>(n);
        byte[][] mtx = new byte[n][n];
        ArrayList<String> an = new ArrayList<>(n);
        sb=new StringBuilder(n);
        for (int i = 0; i < n; i++) {
            an.add("");
            sb.append(".");
        }
        mx = new byte[n];
        my = new byte[n];
        trace(ans, an, n, n, mtx, 0);
        return ans;
    }

    public void trace(List<List<String>> ans, ArrayList<String> an, int n, int cur, byte[][] mtx, int x) {

        if (cur == 0) {
            ans.add((List<String>) an.clone());
            return;
        }
        for (int i = x; i < n; i++) {
            if (mx[i] == 1) {
                continue;
            }
            for (int j = 0; j < n; j++) {
                if (my[j] != 1 && check(mtx, i, j, n)) {
                    mtx[i][j] = 1;
                    mx[i] = 1;
                    my[j] = 1;
                    StringBuilder builder = new StringBuilder(this.sb);
                    builder.setCharAt(j, 'Q');
                    an.set(i, builder.toString());
                    trace(ans, an, n, --cur, mtx, i+1);
                    an.set(i, "");
                    mtx[i][j] = 0;
                    mx[i] = 0;
                    my[j] = 0;
                    cur++;
                }
            }
        }

    }

    public boolean check(byte[][] mtx, int x, int y, int n) {

        for (int i = 0; i < n; i++) {
            if (mtx[x][i] == 1) {
                return false;
            }
        }

        for (int i = 0; i < n; i++) {
            if (mtx[i][y] == 1) {
                return false;
            }
        }

        for (int i = x, j = y; i > 0 && j > 0; i--, j--) {
            if (mtx[i - 1][j - 1] == 1) {
                return false;
            }
        }

        for (int i = x, j = y; i < n - 1 && j < n - 1; i++, j++) {

            if (mtx[i + 1][j + 1] == 1) {
                return false;
            }
        }

        for (int i = x, j = y; i < n - 1 && j > 0; i++, j--) {

            if (mtx[i + 1][j - 1] == 1) {
                return false;
            }
        }

        for (int i = x, j = y; i > 0 && j < n - 1; i--, j++) {

            if (mtx[i - 1][j + 1] == 1) {
                return false;
            }
        }

        return true;
    }

    public static void main(String[] args) {

        byte[][] mtx = {
                {0, 0, 1, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0},
        };

        //  System.out.println(check(mtx, 1, 3, 4));
//
//        for (int i = 0; i < 4; i++) {
//            for (int j = 0; j < 4; j++) {
//                System.out.println("i = " + i + " j = " + j + "   " + check(mtx, i, j, 4));
//            }
//        }

          System.out.println(new Solution().solveNQueens(4));

    }
}

  

  

不超时可以通过了。

优化第4版本,对于当前i,j判断当前行与列是否允许放皇后通过mx,my 单个坐标进行判断,而不是使用二维矩阵:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 如何判断是否是对角线,对应坐标相减结果绝对值相等则对角线: Math.abs(x1 - x2) == Math.abs(y1 - y2);
 */
class Solution {

    StringBuilder sb = null;
    byte[] mx = null;
    byte[] my = null;

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

        List<List<String>> ans = new ArrayList<>(n);
        byte[][] mtx = new byte[n][n];
        ArrayList<String> an = new ArrayList<>(n);
        sb=new StringBuilder(n);
        for (int i = 0; i < n; i++) {
            an.add("");
            sb.append(".");
        }
        mx = new byte[n];
        my = new byte[n];
        trace(ans, an, n, n, mtx, 0);
        return ans;
    }

    public void trace(List<List<String>> ans, ArrayList<String> an, int n, int cur, byte[][] mtx, int x) {

        if (cur == 0) {
            ans.add((List<String>) an.clone());
            return;
        }
        for (int i = x; i < n; i++) {
            if (mx[i] == 1) {
                continue;
            }
            for (int j = 0; j < n; j++) {
                if (my[j] != 1 && check(mtx, i, j, n)) {
                    mtx[i][j] = 1;
                    mx[i] = 1;
                    my[j] = 1;
                    StringBuilder builder = new StringBuilder(this.sb);
                    builder.setCharAt(j, 'Q');
                    an.set(i, builder.toString());
                    trace(ans, an, n, --cur, mtx, i+1);
                    an.set(i, "");
                    mtx[i][j] = 0;
                    mx[i] = 0;
                    my[j] = 0;
                    cur++;
                }
            }
        }

    }

    public boolean check(byte[][] mtx, int x, int y, int n) {
        /*
        for (int i = 0; i < n; i++) {
            if (mtx[x][i] == 1) {
                return false;
            }
        }

        for (int i = 0; i < n; i++) {
            if (mtx[i][y] == 1) {
                return false;
            }
        }
        */
        for (int i = x, j = y; i > 0 && j > 0; i--, j--) {
            if (mtx[i - 1][j - 1] == 1) {
                return false;
            }
        }

        for (int i = x, j = y; i < n - 1 && j < n - 1; i++, j++) {

            if (mtx[i + 1][j + 1] == 1) {
                return false;
            }
        }

        for (int i = x, j = y; i < n - 1 && j > 0; i++, j--) {

            if (mtx[i + 1][j - 1] == 1) {
                return false;
            }
        }

        for (int i = x, j = y; i > 0 && j < n - 1; i--, j++) {

            if (mtx[i - 1][j + 1] == 1) {
                return false;
            }
        }

        return true;
    }

    public static void main(String[] args) {

        byte[][] mtx = {
                {0, 0, 1, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0},
                {0, 0, 0, 0},
        };

        //  System.out.println(check(mtx, 1, 3, 4));
//
//        for (int i = 0; i < 4; i++) {
//            for (int j = 0; j < 4; j++) {
//                System.out.println("i = " + i + " j = " + j + "   " + check(mtx, i, j, 4));
//            }
//        }

          System.out.println(new Solution().solveNQueens(4));

    }
}

  

原文地址:https://www.cnblogs.com/leodaxin/p/11267341.html