Рубрики
Без рубрики

Решение: N-Queens

Это является частью серии пояснений решения LeetCode (индекс). Если вам понравилось это решение или Фу … помечены алгоритмами, JavaScript, Java, Python.

Решения LeetCode (161 часть серии)

Это является частью серии объяснений решения LeetCode ( index ). Если вам понравилось это решение или нашел его полезным, Пожалуйста, как Этот пост и/или УПОТАТЬ Мое решение пост на форумах LeetCode Отказ

Проблема летакода # 51 (HARD): N-Queens

Описание:

( Перейти к : Идея решения Код : JavaScript | Python |. Java |. C ++

N-Queens Головоломка – проблема размещения n Queens на n x n Шахматная доска такая, что ни одно две королевы атакуют друг друга.

Учитывая целое число n , вернуть Все различные решения для N-Queens Puzzle Отказ

Каждое решение содержит отчетливую конфигурацию платы в размещении N-Queens, где 'Q' и '.' Оба указывают на королеву и пустое пространство, соответственно.

Примеры:

Вход:
Выход: [[«.Q ..», «… Q», «Q …», “.. Q.”], [“.. Q.”, “Q …”, ” …Q”,”. Q..”]]
Объяснение: Существует два различных решения для головоломки 4 Queens, как показано выше
Визуальный
Вход:
Выход: [[“Q”]]

Ограничения:

  • 1

Идея:

( Перейти к : Описание проблемы Код : JavaScript | Python |. Java |. C ++

Наивный подход здесь попытается все возможное сочетание мест, но есть (N ^ 2)!/(N ^ 2 – n)! Разные комбинации, которые до ~ 1E17 Когда N . Вместо этого нам нужно убедиться, что мы только попытаемся разместить королевы, где это возможно, чтобы сделать это, основанным на инструкциях. Казалось бы, это позвонит для Глубина первый поиск ( DFS ) Подход с рекурсивный Функция помощника ( Place ), так что мы проводим только работоспособные комбинации, не теряя время на известных мертвых концах.

Во-первых, мы должны учитывать, как будут размещены королевы. Поскольку каждая строка может иметь только одну королеву, наш базовый процесс будет в место королева, а затем решайте следующий ряд. На каждой строке нам придется повторять возможные варианты, проверять ячейку для действительности, то место Королева на доска Отказ Как только рекурсия возврат S, мы можем backtrack и итерацию до следующей клетки в ряд.

Поскольку королева имеет четыре оси атаки, нам нужно проверить три оставшихся оси (кроме горизонтальной строки, которую наша итерация естественным образом позаботится) для действительности. Есть N Возможные столбцы и 2 * N – 1 Возможные диагонали левой нисходящей и правой нисходящей диагонали. С ограничением 1, Каждая из двух диагональных состояний представляет собой до 17 бит «Стоимость данных и вертикальное состояние до 9 бит Итак, мы можем использовать Битовое манипуляция хранить эти состояния эффективно.

Так что для каждого рекурсивного звонка к место Королева, мы должны пройти вдоль государства доска в виде только трех целых чисел ( Vert, Ldiag, Rdiag ). Затем мы можем использовать Bitmasks Чтобы проверить достоверность клетки, прежде чем пытаться восстановить следующую строку.

С нашего доска это N ^ 2 Матрица, мы можем использовать обратно здесь до хорошего эффекта. Если мы успешно доберемся до конца доски без провала, мы должны толкать копию доски с помощью строк в качестве строк на наш массив ответов ( ANS ). ( Примечание : Можно опустить дополнительное пространство только размеру стека рекурсии, O (n) процедурно создавая результаты непосредственно в анс , но это не представляет много экономии космического пространства по сравнению с дополнительной обработкой, которую он требует.)

  • Сложность времени: O (n!) который представляет максимальное количество размещенных королев
  • Космическая сложность: O (N ^ 2) для доски

Код JavaScript:

( Перейти к : Описание проблемы Идея решения

var solveNQueens = function(N) {
    let ans = [],
        board = Array.from({length: N}, () => new Array(N).fill('.'))

    const place = (i, vert, ldiag, rdiag) => {
        if (i === N) {
            let res = new Array(N)
            for (let row = 0; row < N; row++)
                res[row] = board[row].join("")
            ans.push(res)
            return
        }
        for (let j = 0; j < N; j++) {
            let vmask = 1 << j, lmask = 1 << (i+j), rmask = 1 << (N-i-1+j)
            if (vert & vmask || ldiag & lmask || rdiag & rmask) continue
            board[i][j] = 'Q'
            place(i+1, vert | vmask, ldiag | lmask, rdiag | rmask)
            board[i][j] = '.'
        }
    }

    place(0,0,0,0)
    return ans
};

Код Python:

( Перейти к : Описание проблемы Идея решения

class Solution:
    def solveNQueens(self, N: int) -> List[List[str]]:
        ans = []
        board = [['.'] * N for _ in range(N)]

        def place(i: int, vert: int, ldiag: int, rdiag:int) -> None:
            if i == N:
                ans.append(["".join(row) for row in board])
                return
            for j in range(N):
                vmask, lmask, rmask = 1 << j, 1 << (i+j), 1 << (N-i-1+j)
                if vert & vmask or ldiag & lmask or rdiag & rmask: continue
                board[i][j] = 'Q'
                place(i+1, vert | vmask, ldiag | lmask, rdiag | rmask)
                board[i][j] = '.'

        place(0,0,0,0)
        return ans

Java код:

( Перейти к : Описание проблемы Идея решения

class Solution {
    List> ans;
    char[][] board;

    public List> solveNQueens(int N) {
        ans = new ArrayList<>();
        board = new char[N][N];
        for (char[] row : board) Arrays.fill(row, '.');
        place(0,0,0,0);
        return ans;
    }

    private void place(int i, int vert, int ldiag, int rdiag) {
        int N = board.length;
        if (i == N) {
            List res = new ArrayList<>();
            for (char[] row : board) res.add(new String(row));
            ans.add(res);
            return;
        }
        for (int j = 0; j < N; j++) {
            int vmask = 1 << j, lmask = 1 << (i+j), rmask = 1 << (N-i-1+j);
            if ((vert & vmask) + (ldiag & lmask) + (rdiag & rmask) > 0) continue;
            board[i][j] = 'Q';
            place(i+1, vert | vmask, ldiag | lmask, rdiag | rmask);
            board[i][j] = '.';
        }
    }
}

C ++ код:

( Перейти к : Описание проблемы Идея решения

class Solution {
public:
    vector> solveNQueens(int N) {
        ans.clear();
        board.resize(N, string(N, '.'));
        place(0,0,0,0);
        return ans;
    }

private:
    vector> ans;
    vector board;

    void place(int i, int vert, int ldiag, int rdiag) {
        int N = board.size();
        if (i == N) {
            vector res;
            for (auto row : board) res.push_back(row);
            ans.push_back(res);
            return;
        }
        for (int j = 0; j < N; j++) {
            int vmask = 1 << j, lmask = 1 << (i+j), rmask = 1 << (N-i-1+j);
            if (vert & vmask || ldiag & lmask || rdiag & rmask) continue;
            board[i][j] = 'Q';
            place(i+1, vert | vmask, ldiag | lmask, rdiag | rmask);
            board[i][j] = '.';
        }
    }
};

Решения LeetCode (161 часть серии)

Оригинал: “https://dev.to/seanpgallivan/solution-n-queens-5hdb”