본문 바로가기

코딩 테스트/리트코드

[리트코드] 51. N-Queens

반응형

문제

https://leetcode.com/problems/n-queens/description/

 

문제 분석

n x n 크기의 판에 Queen 들을 안전하게 놓는 방법을 구하는 문제이다.

Queen 은 가로, 세로, 대각선으로 공격을 한다.

 

n = 4 일 경우는 위의 두가지 방법이 존재한다.

 

조건에 1 <= n <= 9 로 충분히 n 이 작기 때문에 완전탐색으로 문제를 풀 수 있을 거 같다.

 

접근 방법

DFS 를 활용한 완전탐색으로 문제를 해결하였다.

row 당 Queen 이 하나 올 수 있기 때문에 row 를 depth 로 사용하였고 queen 을 놓을때 마다 map 에 놓을 수 없는 위치를 표시하였다.

그 후 row + 1 을 하여 재귀 호출을 하였다.

 

코드

import java.util.*;

class Solution {
    public List<List<String>> solveNQueens(int n) {
        int[][] map = new int[n][n];
        List<List<String>> answer = new ArrayList<>();
        List<List<Integer>> result = new ArrayList<>();

        dfs(0, new ArrayList<>(), result, map);

        for(List<Integer> list : result){
            List<String> strList = new ArrayList<>();
            for(int idx : list){
                String str = "";
                for(int i=0; i<idx; i++){
                    str += ".";
                }
                str += "Q";
                for(int i=idx+1; i<n; i++){
                    str += ".";
                }
                strList.add(str);
            }
            answer.add(strList);
        }
        
        return answer;
    }

    public void dfs(int row, List<Integer> cur, List<List<Integer>> result, int[][] map){
        if(row == map.length){
            result.add(new ArrayList<>(cur));
            return;
        }

        for(int col = 0; col < map.length; col++){
            if(map[row][col] == 0){
                int[][] markingMap = mark(map, row, col);
                cur.add(col);
                dfs(row+1, cur, result, markingMap);
                cur.remove(cur.size()-1);
            }
        }
    }

    public int[][] mark(int[][] map, int row, int col){
        int n = map.length;
        int[][] result = new int[n][n];
        
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                result[i][j] = map[i][j];
            }
        }

        for(int i=0; i<n; i++){
            result[i][col] = 1;
            result[row][i] = 1;
        }

        int nextR = row;
        int nextC = col;

        while(nextR >= 0 && nextR < n && nextC >= 0 && nextC < n){
            result[nextR++][nextC++] = 1;
        }
        
        nextR = row;
        nextC = col;

        while(nextR >= 0 && nextR < n && nextC >= 0 && nextC < n){
            result[nextR++][nextC--] = 1;
        }

        return result;
    }
}

 

결과를 문자열 리스트로 만드는 과정이 깔끔하지 않았다. 

문자열을 다루는 것이 아직도 미숙하다. 좀 더 개선이 필요하다.

 

 

코드 개선

import java.util.*;

class Solution {
    public List<List<String>> solveNQueens(int n) {
        char[][] board = new char[n][n];
        for(char[] arr : board){
            Arrays.fill(arr, '.');
        }
        List<List<String>> result = new ArrayList<>();

        dfs(0, board, result);
        return result;
    }

    public void dfs(int row, char[][] board, List<List<String>> result){
        if(row == board.length){
            result.add(changeList(board));
            return;
        }

        for(int col=0; col<board.length; col++){
            if(isValid(row, col, board)){
                board[row][col] = 'Q';
                dfs(row+1, board, result);
                board[row][col] = '.';
            }
        }
    }

    public boolean isValid(int row, int col, char[][] board){
        for(int i=0; i<board.length; i++){
            if(board[i][col] == 'Q') return false;
        }

        int nextR = row;
        int nextC = col;

        while(nextR>=0 && nextR<board.length && nextC>=0 && nextC<board.length){
            if(board[nextR][nextC] == 'Q'){
                return false;
            }

            nextR--;
            nextC++;
        }

        nextR = row;
        nextC = col;

        while(nextR>=0 && nextR<board.length && nextC>=0 && nextC<board.length){
            if(board[nextR][nextC] == 'Q'){
                return false;
            }
            
            nextR--;
            nextC--;
        }

        return true;
    }

    public List<String> changeList(char[][] board){
        List<String> result = new ArrayList<>();

        for(char[] arr : board){
            result.add(new String(arr));
        }

        return result;
    }
}
반응형

'코딩 테스트 > 리트코드' 카테고리의 다른 글

[리트코드] 207. Course Schedule  (0) 2024.02.01
[리트코드] 743. Network Delay Time  (0) 2024.01.31
[리트코드] 529. Minesweeper  (0) 2024.01.21