Problem


매 초마다 움직이며 냄새를 뿌리는 상어들이 여러 마리 존재합니다.

각 상어들은 자신들이 바라보는 방향과 기준에 따라서 다음으로 움직일 방향을 선정합니다.

상어들이 같은 격자에 동시에 들어가게 되면 숫자가 작은 상어만 남고 나머지는 전부 내보냅니다.

가장 강한 1 번 상어가 남는 시간은 몇 초 뒤인지 구하는 문제입니다.



Solution

1 번 상어가 남거나 1000 초가 지날 때까지 다음 순서대로 반복하면 됩니다.

  1. moveShark() : 상어 이동
    • 다음 방향 계산
    • 이동
    • 경쟁을 통해 작은 번호의 상어 생존
  2. decreaseSmellTime() : 모든 냄새들 1 씩 감소
  3. createSmell() : 상어가 이동한 자리에 새로운 냄새 생성


주의할점

  1. 상어가 이동한 후에는 상어의 방향을 이동한 방향으로 바꿔주어야 합니다.
  2. 위 순서에서 2번과 3번을 바꾸게 되면 상어가 새로운 냄새를 생성하자마자 1 씩 깎이기 때문에 순서를 지켜야 합니다.
  3. 상어 리스트를 for 문으로 돌면서 경쟁에서 패배한 상어를 바로 제거하니 런타임 에러가 발생했습니다. for 문 도중에는 요소를 삭제하지 말고 기록해두었다가 나중에 삭제합니다.


Shark Class

  • 상어의 넘버, 좌표, 현재 방향과 우선 순위를 갖고 있습니다.
  • 우선 순위는 priority[현재 방향][우선 순위] 형태입니다.
  • findNextDir 함수는 상어가 다음으로 이동할 방향을 구합니다.
  • 현재 상어의 방향을 기준으로 우선순위가 높은 방향부터 candiates 셋에 존재하는지 확인합니다.
  • candidates 셋은 상어가 이동할 수 있는 방향들을 갖고 있습니다.


arr, smellOwner, leftTime

  • 각각 상어의 위치, 냄새의 주인, 냄새들의 남은 시간을 기록한 2 차원 배열입니다.


noSmellSet, mySmellSet

  • 상어가 이동할 수 있는 공간을 미리 구하기 위해 사용합니다.
  • 상어는 먼저 냄새가 없는 곳을 찾고 만약 4방향 전부 냄새가 존재한다면 자기 냄새가 있는 방향으로 이동합니다.
  • 이동할 수 있는 곳은 여러 개가 될 수 있기 때문에 Set 자료구조에 저장하고 상어의 현재 방향에 따른 우선순위를 통해 비교합니다.


willRemove

  • 경쟁에서 뒤쳐진 상어는 제거해야 합니다.
  • 한번에 여러 마리가 겹칠 수 있기 때문에 Queue 에 담아둡니다.



Java Code

import java.util.*;
import java.io.*;

class Main {
    // 1, 2, 3, 4 는 각각 위, 아래, 왼쪽, 오른쪽
    static class Shark {
        int id, x, y, dir;
        int[][] priority = new int[5][5];

        Shark() { }

        int findNextDir(Set<Integer> candidates) {
            for (int i = 1; i < 5; i++) {
                if (candidates.contains(priority[dir][i])) {
                    return priority[dir][i];
                }
            }
            return 0;
        }
    }

    static int N, M, k;
    static int[][] arr = new int[21][21];
    static int[][] smellOwner = new int[21][21];
    static int[][] leftTime = new int[21][21];
    static Map<Integer, Shark> sharks = new HashMap<>();
    static int time = 0;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        // input
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken());

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());

            for (int j = 0; j < N; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());

                if (arr[i][j] > 0) {
                    Shark s = new Shark();
                    s.id = arr[i][j];
                    s.x = i;
                    s.y = j;
                    sharks.put(s.id, s);
                    
                    smellOwner[i][j] = s.id;
                    leftTime[i][j] = k;
                }
            }
        }

        // direction of sharks
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < M; i++) {
            Shark s = sharks.get(i + 1);
            s.dir = Integer.parseInt(st.nextToken());
        }

        // priority of sharks
        for (int i = 0; i < M; i++) {
            Shark s = sharks.get(i + 1);

            for (int j = 0; j < 4; j++) {
                st = new StringTokenizer(br.readLine());

                for (int z = 0; z < 4; z++) {
                    s.priority[j + 1][z + 1] = Integer.parseInt(st.nextToken());
                }
            }
        }

        // solution
        solution();
    }

    static void solution() {
        while (time++ < 1000) {
            moveShark();
            decreaseSmellTime();
            createSmell();

            if (sharks.size() == 1) {
                System.out.println(time);
                return;
            }
        }

        System.out.println(-1);
    }

    // 상어 이동 후 겹친 애 쫓아내기
    static void moveShark() {
        // dx dy 는 위, 아래, 왼쪽, 오른쪽 순서
        int[] dx = {-1, 1, 0, 0};
        int[] dy = {0, 0, -1, 1};
        Queue<Integer> willRemove = new LinkedList<Integer>();

        for (Integer id : sharks.keySet()) {
            Set<Integer> noSmellSet = new HashSet<>();
            Set<Integer> mySmellSet = new HashSet<>();
            Shark s = sharks.get(id);

            for (int i = 0; i < 4; i++) {
                int nx = s.x + dx[i];
                int ny = s.y + dy[i];

                if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;

                if (smellOwner[nx][ny] == 0) {
                    noSmellSet.add(i + 1);
                } else if (smellOwner[nx][ny] == s.id) {
                    mySmellSet.add(i + 1);
                }
            }

            // 냄새 없는 곳부터 스캔하고 자기 냄새 있는 곳을 스캔해서 이동할 방향 구하기
            int nextDir = s.findNextDir(noSmellSet);

            if (nextDir == 0) {
                nextDir = s.findNextDir(mySmellSet);
            }

            // 상어 이동
            arr[s.x][s.y] = 0;
            if (nextDir == 1) {
                s.x -= 1;
            } else if (nextDir == 2) {
                s.x += 1;
            } else if (nextDir == 3) {
                s.y -= 1;
            } else if (nextDir == 4) {
                s.y += 1;
            }
            
            // 이동할 위치에 상어 있으면 경쟁 후 작은 번호가 승리
            if (arr[s.x][s.y] == 0 || s.id < arr[s.x][s.y]) {
                arr[s.x][s.y] = s.id;
                s.dir = nextDir;
            } else {
                willRemove.add(s.id);
            }
        }

        while (!willRemove.isEmpty()) {
            sharks.remove(willRemove.poll());
        }
    }

    // 맵 전체의 냄새 시간을 하나씩 감소 시키고 0 이 되면 냄새 주인 정보도 지움
    static void decreaseSmellTime() {
        for(int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (leftTime[i][j] == 0) continue;

                leftTime[i][j]--;

                if (leftTime[i][j] == 0) {
                    smellOwner[i][j] = 0;
                }
            }
        }
    }

    // 상어가 이동한 곳에 새로운 냄새 생성
    static void createSmell() {
        for (Integer id : sharks.keySet()) {
            Shark s = sharks.get(id);

            smellOwner[s.x][s.y] = s.id;
            leftTime[s.x][s.y] = k;
        }
    }
}


Problem


T 초가 지난 후 남아있는 미세 먼지들의 총 합을 구하는 문제입니다.



Solution

구현 문제입니다.

  1. 미세먼지 확산
  2. 공기청정기 가동


주의할 점은 미세먼지 확산 시 기존 배열 (아래 코드에서는 arr) 을 바로 수정하지 않는 겁니다.

예를 들어 (1, 1) = 5, (1, 2) = 9 의 미세머지가 있다고 가정합니다.

만약 기존 배열을 그대로 수정하면 (1, 1) 에 있던 미세먼지를 먼저 확산시켜서 (1, 2) 의 미세먼지가 10 이 되고

반복문이 (1, 2) 위치에 도달했을 때 10 을 기준으로 확산하기 때문에 주변에 2 씩 퍼지게 됩니다.

그래서 미세먼지의 확산 결과를 temp 배열에다가 담았다가 arr 배열에 덮어쓰는 형식으로 구현했습니다.

공기청정기는 그냥 노가다로 구현했습니다.



Java Code

import java.util.*;
import java.io.*;

class Main {
    static int R, C, T;
    static int[][] arr = new int[50][50];
    static List<Integer> airCleanerRows = new ArrayList<>();
    static int sumOfDust = 2;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        // input
        st = new StringTokenizer(br.readLine());
        R = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());
        T = Integer.parseInt(st.nextToken());

        for (int i = 0; i < R; i++) {
            st = new StringTokenizer(br.readLine());

            for (int j = 0; j < C; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
                sumOfDust += arr[i][j];

                if (arr[i][j] == -1) {
                    airCleanerRows.add(i);
                }
            }
        }

        // solution
        solution();
    }

    static void solution() {
        while (T-- > 0) {
            // 1. 먼지 확산
            arr = spreadDust();

            // 2. 공기청정기 가동
            executeAirCleaner();
        }

        System.out.println(calculateSum());
    }

    static int[][] spreadDust() {
        int[][] temp = new int[50][50];
        int[] dx = {-1, 1, 0, 0};
        int[] dy = {0, 0, -1, 1};

        // 확산된 미세먼지를 temp 배열에 계산
        for (int x = 0; x < R; x++) {
            for (int y = 0 ; y < C; y++) {
                if (arr[x][y] == -1) {
                    temp[x][y] = -1;
                    continue;
                }

                temp[x][y] += arr[x][y];

                for (int i = 0; i < 4; i++) {
                    int nx = x + dx[i];
                    int ny = y + dy[i];

                    if (nx < 0 || nx >= R || ny < 0 || ny >= C) continue;
                    if (arr[nx][ny] == -1) continue;

                    temp[nx][ny] += (arr[x][y] / 5);
                    temp[x][y] -= (arr[x][y] / 5);
                }
            }
        }

        return temp;
    }

    static void executeAirCleaner() {
        // 위쪽 공기청정기는 반시계방향
        int top = airCleanerRows.get(0);

        for (int x = top - 1; x > 0; x--) {
            arr[x][0] = arr[x-1][0];
        }
        
        for (int y = 0; y < C - 1; y++) {
            arr[0][y] = arr[0][y+1];
        }

        for (int x = 0; x < top; x++) {
            arr[x][C-1] = arr[x+1][C-1];
        }
        
        for (int y = C - 1; y > 1; y--) {
            arr[top][y] = arr[top][y-1];
        }

        arr[top][1] = 0;
        

        // 아래쪽 공기청정기는 시계 방향
        int bottom = airCleanerRows.get(1);
        
        for (int x = bottom + 1; x < R - 1; x++) {
            arr[x][0] = arr[x+1][0];
        }

        for (int y = 0; y < C - 1; y++) {
            arr[R-1][y] = arr[R-1][y+1];
        }

        for (int x = R - 1; x > bottom; x--) {
            arr[x][C-1] = arr[x-1][C-1];
        }

        for (int y = C - 1; y > 1; y--) {
            arr[bottom][y] = arr[bottom][y-1];
        }

        arr[bottom][1] = 0;
    }

    static int calculateSum() {
        int sum = 2;

        for (int x = 0; x < R; x++) {
            for (int y = 0; y < C; y++) {
                sum += arr[x][y];
            }
        }
        
        return sum;
    }
}


Problem


모든 승객들을 도착지에 옮겨주고 난 뒤 남은 연료의 양을 출력하는 문제입니다.

승객들을 데리러 가는 기준은 가까운 기준이며 같은 거리에 여러 명의 승객이 있다면 행 번호가 가장 작고 열 번호가 가장 작은 승객을 데리러 갑니다.



Solution

귀찮은 구현 문제입니다.

아래 과정을 계속 반복하면 됩니다.

  1. BFS 를 사용하여 승객 찾기
  2. 가장 가까운 승객 비교
  3. 도착지에 데려다줌
  4. 연료 확인


주의사항도 있습니다.

  1. A 의 도착지와 B 의 출발지가 같은 경우 존재 -> 택시의 현재 위치도 검사
  2. 도착지는 겹칠 수 있음 -> 도착지를 특정해놓고 BFS 를 진행
  3. 행과 열 우선순위 헷갈리지 않게 주의
  4. 연료는 많은데 벽에 막혀서 출발지 또는 도착지로 가지 못하는 경우 -> 승객을 태우거나 내리지 못했는데 BFS 가 끝나진 않았는지 확인


변수

변수설명
Taxi Class택시 클래스입니다. BFS 에서 좌표를 담아두기 위해 사용하며 택시가 이동한 거리인 move 변수를 갖고 있습니다.
Passenger Class승객 클래스입니다. 승객의 아이디, 출발지와 도착지 좌표를 갖고 있습니다. 아이디는 2 부터 시작합니다.
taken현재 타고 있는 승객입니다. null 이면 아무도 타지 않은 상태, 누군가 타고 있다면 해당 승객 객체가 들어갑니다.
passMap승객 리스트입니다. 승객이 도착지에 내릴 때마다 해당 승객을 지워가면서 모든 승객이 내렸는지 체크합니다.
candidates택시로부터 같은 거리에 있는 승객들입니다. 택시에 탈 수 있는 후보들이며 행과 열을 비교하기 위해 사용합니다.


가장 가까운 승객 비교하기

Taxi 클래스에 있는 move 변수를 이용하면 특정 좌표에 도달했을때 택시 위치로부터 얼만큼 이동했는지 알 수 있습니다.

BFS 를 진행하면서 승객 위치에 도달하면 candidates 큐에 담아둡니다.

prevMove 변수를 사용해서 이전 move 를 기억하고 있다가 둘이 달라지는 순간에 candidates 큐에 값이 있는지 없는지 검사합니다.

만약 값이 없으면 계속 BFS 를 진행하면 되고 값이 있다면 최단거리인 승객들을 이미 찾았기 때문에 break 로 빠져나옵니다.

candidates 큐에 있는 승객들은 모두 거리가 같기 때문에 행과 열을 비교하여 조건에 맞는 승객을 찾아서 태웁니다.

우선순위 큐를 쓰면 큐에 넣을때마다 매번 비교를 하기 때문에 그냥 일반큐로 하고 나중에 비교했습니다.


도착지에 데려다줌

taken 으로 타고 있는 승객의 정보를 알 기 때문에 도착지 좌표에 도달할 때까지 BFS 를 진행하면 됩니다.


연료 확인

BFS 가 끝나면 prevMove 값을 반환합니다.

이동한 거리, 즉 사용한 연료기 때문에 전체 연료량과 연산한 뒤 음수가 되는지 확인하면 됩니다.

벽에 막혀서 연료가 충분한데 도달할 수 없거나 이동 중에 연료가 떨어지면 Integer.MAX_VALUE 를 리턴하여 fuel 값을 음수로 만들어줍니다.



Java Code

import java.util.*;
import java.io.*;

class Main {
    static class Taxi {
        int x, y, move;

        Taxi(int x, int y, int move) {
            this.x = x;
            this.y = y;
            this.move = move;
        }
    }

    static class Passenger {
        int id, sx, sy, ex, ey;

        Passenger() { }
    }

    static int N, M, fuel;
    static int[][] arr = new int[21][21];
    static Taxi taxi;
    static Passenger taken = null;
    static Map<Integer, Passenger> passMap = new HashMap<>();

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        // input
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        fuel = Integer.parseInt(st.nextToken());

        for (int i = 1; i < N + 1; i++) {
            st = new StringTokenizer(br.readLine());

            for (int j = 1; j < N + 1; j++) {
                arr[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        st = new StringTokenizer(br.readLine());
        taxi = new Taxi(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), 0);

        for (int i = 0; i < M; i++) {
            st = new StringTokenizer(br.readLine());

            Passenger p = new Passenger();
            p.id =  i + 2;  // 벽이 1 이라서 2 부터 넘버링
            p.sx = Integer.parseInt(st.nextToken());
            p.sy = Integer.parseInt(st.nextToken());
            p.ex = Integer.parseInt(st.nextToken());
            p.ey = Integer.parseInt(st.nextToken());

            passMap.put(p.id, p);

            // 출발지는 겹치지 않기 때문에 맵에 기록
            arr[p.sx][p.sy] = p.id;
        }

        // solution
        solution();
    }

    // 모든 승객을 데려다 줄때까지 BFS 를 반복하며 연료의 양을 확인한다.
    static void solution() {
        while (!passMap.isEmpty()) {
            int toStartFuel = bfs();
            fuel -= toStartFuel;

            if (fuel < 0) break;

            int toDestFuel = bfs();
            fuel -= toDestFuel;

            if (fuel < 0) break;

            fuel += toDestFuel * 2;
        }

        System.out.println(fuel < 0 ? -1 : fuel);
    }

    static int bfs() {
        Queue<Taxi> q = new LinkedList<>();
        Queue<Passenger> candidates = new LinkedList<>();
        boolean[][] visited = new boolean[21][21];
        int[] dx = {-1, 1, 0, 0};
        int[] dy = {0, 0, -1, 1};
        
        int prevMove = taxi.move;
        visited[taxi.x][taxi.y] = true;
        q.add(taxi);

        while (!q.isEmpty()) {
            Taxi now = q.poll();

            // 이동 중에 연료가 떨어지면 종료
            if (fuel - now.move < 0) {
                return Integer.MAX_VALUE;
            }

            // 택시 이동 시간대가 다르고 candidates 가 이미 존재하면 break
            if (prevMove != now.move && !candidates.isEmpty()) {
                break;
            }

            prevMove = now.move;

            if (taken == null) {
                // 택시가 비어있는 경우 가장 가까운 승객 후보를 만나면 candidates 에 추가
                int id = arr[now.x][now.y];

                if (id > 1) {
                    Passenger p = passMap.get(id);
                    candidates.add(p);
                }
            } else {
                // 택시에 승객이 있는 경우 도착지를 만나면 종료
                if (now.x == taken.ex && now.y == taken.ey) {
                    passMap.remove(taken.id);
                    taken = null;
                    taxi = new Taxi(now.x, now.y, 0);
                    return prevMove;
                }
            }

            // 동서남북 이동
            for (int i = 0 ; i < 4; i++) {
                int nx = now.x + dx[i];
                int ny = now.y + dy[i];

                if (0 < nx && nx < N+1 && 0 < ny && ny < N+1) {
                   if (arr[nx][ny] != 1 && visited[nx][ny] == false) {
                       q.add(new Taxi(nx, ny, now.move + 1));
                       visited[nx][ny] = true;
                   } 
                }
            }
        }

        // while 문이 끝났는데 candidates 에 아무것도 없으면 벽에 막혀서 도달못함
        if (candidates.isEmpty()) {
            return Integer.MAX_VALUE;
        }

        taken = findNearest(candidates);
        taxi = new Taxi(taken.sx, taken.sy, 0);
        arr[taken.sx][taken.sy] = 0;
        return prevMove;
    }

    // 같은 거리면 x 가 작고, y 가 작은 사람으로
    static Passenger findNearest(Queue<Passenger> q) {
        Passenger target = q.poll();

        while (!q.isEmpty()) {
            Passenger compare = q.poll();

            if (compare.sx < target.sx) {
                target = compare;
            } else if (compare.sx == target.sx && compare.sy < target.sy) {
                target = compare;
            }
        }

        return target;
    }
}


Problem


nums 배열에 있는 각 숫자에 + 또는 - 중 하나를 선택해서 전부 계산할 경우 S 와 같은 값이 나오는 경우의 수는 몇 가지인지 찾는 문제입니다.



Solution

DFS 를 이용해서 모든 경우의 수를 찾아주면 됩니다.

index 를 하나씩 증가시키면서 nums[index] 를 더하는 경우, 빼는 경우를 차례대로 확인합니다.



Java Code

class Solution {
    public int findTargetSumWays(int[] nums, int S) {
        return dfs(nums, S, 0, 0);
    }
    
    private int dfs(int[] nums, int S, int index, int sum) {
        if (index == nums.length) {
            return S == sum ? 1 : 0;
        }
        
        return dfs(nums, S, index + 1, sum + nums[index]) +
               dfs(nums, S, index + 1, sum - nums[index]);
    }
}


Problem


Medium 문제입니다.

주어진 문자열 S 를 나누었을 때 각 파트는 다른 파트와 중복된 문자가 없어야 합니다.

예를 들어 a, b, c 세 파트로 나눈다면 a 파트에 존재하는 문자는 b, c 파트에 존재하지 않아야 합니다.

위 조건을 만족하면서 최대한 많은 파트로 쪼갰을 때 각각의 길이를 List 에 담아 리턴하면 됩니다.



Solution

for 문을 총 두번 돕니다.

첫 번째 for 문에서는 각 문자들이 마지막으로 등장하는 index 를 저장해둡니다.

두 번째 for 문에서는 현재 지나고 있는 문자들 중 가장 마지막에 나오는 문자의 index 를 저장해둔 뒤 i 가 그 index 에 도달했을 때, 더 이상 중복되는 문자는 나오지 않는다고 판단하여 길이를 저장합니다.


주어진 문자 "ababcbacadefegdehijhklij" 로 예를 들면

"ababcbaca" 문자열이 진행되는 동안 farRight 변수는 8 입니다.

마지막 'a' 를 만나는 순간 i == farRight 가 되고 지금까지 나온 문자들은 이후에는 절대 나오지 않는다 라는 걸 알 수 있습니다.

리스트에 start 부터 farRight 까지의 길이를 넣어두고 다음 문자부터 다시 위 과정을 반복하면 됩니다.



Java Code

class Solution {
    public List<Integer> partitionLabels(String S) {
        int[] lastIndexs = new int[26];

        for (int i = 0; i < S.length(); i++) {
            lastIndexs[S.charAt(i) - 'a'] = i;
        }
        
        List<Integer> list = new ArrayList<>();
        int start = 0;
        int farRight = 0;
        
        for (int i = 0; i < S.length(); i++) {
            farRight = Math.max(farRight, lastIndexs[S.charAt(i) - 'a']);
            
            if (i == farRight) {
                list.add(farRight - start + 1);
                start = i + 1;
            }
        }
        
        return list;
    }
}


Problem


Easy 문제입니다.

문자열 s 가 특정 substring 의 반복으로만 이루어진 경우를 찾는 문제입니다.



Solution

substring 을 구한 후 반복해서 붙인 다음 s 와 비교하면 됩니다.

순서대로 나열하면 다음과 같습니다.

  1. substring 의 길이를 s 의 절반부터 시작해서 1 까지 확인한다. (절반보다 길면 substring 이 반복될 수가 없음)
  2. s 의 길이가 substring 의 길이와 나누어 떨어지는 지 확인한다.
  3. substring 을 반복해서 붙인 다음 s 와 비교한다.
  4. 일치하는게 나올 때까지 확인한다.



Java Code

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        for (int len = s.length() / 2; len > 0; len--) {
            if (s.length() % len != 0) {
                continue;
            }
            
            int repeatCount = s.length() / len;
            String pattern = s.substring(0, len);
            StringBuilder sb = new StringBuilder();
            
            while (repeatCount-- > 0) {
                sb.append(pattern);
            }
            
            if (sb.toString().equals(s)) {
                return true;
            }
        }
        
        return false;
    }
}


Problem


Easy 문제입니다.

트리가 주어졌을 때 가장 아래쪽에 있고 가장 왼쪽에 있는 노드의 값을 구하는 문제입니다.



Solution

단순하게 풀면 됩니다.

최고 깊이 maxDepth 와 리턴할 결과값 result 를 인스턴스 변수로 선언합니다.

Preorder 로 트리를 순회하면 depth 가 1 높아졌을 때 마주하는 노드가 가장 왼쪽에 있는 노드입니다.

depth 가 1 높아지는 순간의 노드값을 저장해두면서 트리를 모두 순회하면 됩니다.

시간복잡도는 O(n) (n 은 노드의 갯수) 입니다.



Java Code

class Solution {
    int maxDepth = 0;
    int result = 0;
        
    public int findBottomLeftValue(TreeNode root) {
        goChild(root, 1);
        return result;
    }
    
    public void goChild(TreeNode node, int depth) {
        if (node == null) {
            return;
        }
        
        if (depth > maxDepth) {
            result = node.val;
            maxDepth = depth;
        }
        
        goChild(node.left, depth + 1);
        goChild(node.right, depth + 1);
    }
}


Problem


Easy 난이도의 문제입니다.

주어진 숫자 n 을 이진수로 바꾸었을 때 0 과 1 이 연속으로 나오는 구간이 있는지 없는지 판단하는 문제입니다.



Solution

n 을 이진수로 바꾸어 줍니다.

길이가 1 이라면 반복되는 구간이 없기 때문에 항상 true 입니다.

인덱스 0 에 해당하는 문자 even 을 구하고 이와 반대되는 문자 odd 를 구합니다.

이진수 String 을 순회하며 인덱스가 짝수일 때와 홀수일 때 각각 even 과 odd 와 일치하는 지 확인합니다.

시간복잡도는 O(n) 입니다.



Java Code

class Solution {
    public boolean hasAlternatingBits(int n) {
        String bit = Integer.toString(n, 2);
        
        if (bit.length() == 1) {
            return true;
        }
        
        char even = bit.charAt(0);
        char odd = even == '0' ? '1' : '0';
        
        for (int i = 0; i < bit.length(); i++) {
            if (i % 2 == 0 && even != bit.charAt(i)) {
                return false;
            }
            
            if (i % 2 != 0 && odd != bit.charAt(i)) {
                return false;
            }
        }
        
        return true;
    }
}


+ Recent posts