ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [KAKAO] 동굴탐험 (2020 KAKAO 인턴십)
    KAKAO/level 4 2021. 5. 7. 11:30

    조만간 코딩 테스트가 있기도하고, 감이 좀 무뎌진것 같아 프로그래머스백준의 문제들을 풀었다.

     

    요즘은 새로운 문제들을 풀기 앞서 좀 더 기초를 다지는 느낌으로 풀었던 문제들을 다시 효율적이고 빠르게 풀어보는

    연습을 하고 있는 중이다.

     

    옛날 C++로 풀었던 삼성 구현 문제들도 풀어보고, 카카오 관련 구현 + 알고리즘 문제들을 풀었다.

    문제를 풀면서 느끼는 바로는 각 기업만의 색깔이 문제에서 묻어나는 듯 했다. 뭔가 삼성은 풀 집중력으로 어떻게든 디버깅과

    구현을 한다면 풀 수 있는 느낌이 강했고, 카카오는 생각이 떠오르지 않으면 못 푸는 문제들도 있었고 효율성 문제들은

    +a 까지 생각 해줘야하는 문제들이 많았다.

     

    삼성 문제들을 풀면서 각 문제의 복잡한 요구사항들을 시뮬레이션 하며, 머릿속으로 그려보는 연습이 많이 되었다.

    카카오 문제들은 위의 연습도 될 뿐 아니라, 문제 해결 능력이 길러진 느낌이었다.

     

    물론 기업의 문제들이 아니더라도 이러한 부분을 기를 순 있었다. 물론 테스트케이스가 너무 빡빡하거나, 어찌보면 문제의 

    요구사항들이 애매한 문제들은 풀면서 시간이 많이 아까웠던 것 같다.

     

    그래서 그런지  더욱 기업 문제들을 많이 풀어보려 했던게 아닌가 싶다.. ㅎ

     

    다시 기본기를 잡고 쉬운 문제들 부터 풀어보면서 이번엔 프로그래머스level4 문제를 풀어보았다.

    역시 쉽게 풀리면 재미가 없나보다. 어제 밤에 친구들과 같이 풀다가 집중도 안되고 뭔가 잘 안 풀리지 않아 아침에 다시 풀어보고자 했다.

     

    다행히 다시 문제를 보고 나니 생각보단 쉽게 풀렸다. 물론 두 가지 방법들을 시도 해봤는데, 하나는 실패.. ㅋㅋ

     

    그럼 문제를 풀어보자.

     

    programmers.co.kr/learn/courses/30/lessons/67260

     

    코딩테스트 연습 - 동굴 탐험

    9 [[0,1],[0,3],[0,7],[8,1],[3,6],[1,2],[4,7],[7,5]] [[8,5],[6,7],[4,1]] true 9 [[8,1],[0,1],[1,2],[0,7],[4,7],[0,3],[7,5],[3,6]] [[4,1],[5,2]] true 9 [[0,1],[0,3],[0,7],[8,1],[3,6],[1,2],[4,7],[7,5]] [[4,1],[8,7],[6,5]] false

    programmers.co.kr

     

    문제를 맞이하면 조건들이 좀 어렵게 꼬여 있었다.

    • 양방향으로 이어져 있는 방
    • 서로 다른 두 방을 직접 연결하는 통로는 한 개
    • 임의의 두 방의 최단거리는 한 가지 이동 불가능 한 방은 없음
    • path 배열의 길이는 n-1

    여기서 유추 할 수 있었던 것은 양방향 간선, 사이클 없음 두 가지 이다. 

    방의 개수가 n 인 것과 path 배열의 길이가 n-1 인 것을 유추해 본다면 사이클이 없음을 알 수 있다.

     

    먼저 방문해야하는 방이 있으므로 위상정렬일 것 같은 느낌이 들었다. 하지만 어떻게 응용을 해야할까..

     

    그냥 위상정렬만 이용해서 노드에 추가하며 풀어 본 것 (틀림)

    from collections import deque
    
    def solution(n, path, order):
        answer = True
        
        node = [[] for i in range(n)]
        degree = [0 for i in range(n)]
        for p in path:
            start, end = p
            node[start].append(end)
            node[end].append(start)
        
        priority = [[] for i in range(n)]
        for o in order:
            before, after = o
            priority[before].append(after)
            degree[after] += 1
            
        if degree[0] > 0:
            return False
        
        q = deque()   
        check = [0 for i in range(n)]
        check[0] = 1
        q.append(0)
                                
        while q:
            vertax = q.popleft()
            for ver in node[vertax]:
                if check[ver] == 0 and degree[ver] == 0:
                    check[ver] = 1
                    q.append(ver)
            
            for ver in priority[vertax]:
                degree[ver] -=1
                if degree[ver] == 0:
                    check[ver] = 1
                    q.append(ver)
        
        return False if min(check) == 0 else True

     

     

    간단한 문제를 보도록 해보자.

     

    n = 5, orders = [2, 1] 이라 가정해보자. (path는 직접 그림으로 대체하겠다.)

     

    예시 1

    위상정렬대로 풀어보았을 때 위의 case는 통과 한다.

     

    하지만, 이 문제를 보도록 해보자.

     

    n = 6, path = [2, 4], [5, 1] 일때

    예시 2

    이렇게 되면 2번을 보았을 때 4번의 degree -= 1 이 되면서 4번의 degree = 0 이 되어 4번을 넣게 된다.

    4번을 들어가기 위해선 1번을 들어가야 하고, 5번을 들어가야 1번을 들어갈 수 있으므로 여기서 예외 케이스가 발생한다.

     

    여기서 고민을 했다가 떠오른 아이디어는 degree = 0 이 되는 순간 주변 노드를 탐색하며

    주변 노드들 중 방문을 했었던 노드가 있는 지 검사를 해주고, 만약 방문 했었다면 그 노드는 들어갈 수 있으므로 deuqe에 넣어준다.

     

    최종 코드

    from collections import deque
    
    def solution(n, path, order):
        answer = True
        
        node = [[] for i in range(n)]
        degree = [0 for i in range(n)]
        for p in path:
            start, end = p
            node[start].append(end)
            node[end].append(start)
        
        priority = [[] for i in range(n)]
        for o in order:
            before, after = o
            priority[before].append(after)
            degree[after] += 1
            
        if degree[0] > 0:
            return False
        
        q = deque()   
        check = [0 for i in range(n)]
        check[0] = 1
        q.append(0)
                                
        while q:
            vertax = q.popleft()
            for ver in node[vertax]:
                if check[ver] == 0 and degree[ver] == 0:
                    check[ver] = 1
                    q.append(ver)
            
            for ver in priority[vertax]:
                degree[ver] -=1
                if degree[ver] == 0:
                    flag = False
                    for v in node[ver]:
                        if check[v]:
                            flag = True
                            break
                    if not flag:
                        continue
                    check[ver] = 1
                    q.append(ver)
        
        return False if min(check) == 0 else True

     

    물론 더 좋은 코드가 있을 법 하지만, 여기까지 포스팅을 마무리 하겠다.

    'KAKAO > level 4' 카테고리의 다른 글

    [KAKAO] 가사 검색 - 트라이, 이분탐색 (2020 KAKAO BLIEND)  (0) 2021.09.08

    댓글

Designed by Tistory.