[Leetcode] 310. Minimum Height Trees

Jonghae Park·2021년 12월 16일
0

영혼의 알고리즘

목록 보기
18/19

Problem

A tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.

Given a tree of n nodes labelled from 0 to n - 1, and an array of n - 1 edges where edges[i] = [ai, bi] indicates that there is an undirected edge between the two nodes ai and bi in the tree, you can choose any node of the tree as the root. When you select a node x as the root, the result tree has height h. Among all possible rooted trees, those with minimum height (i.e. min(h)) are called minimum height trees (MHTs).

Return a list of all MHTs' root labels. You can return the answer in any order.

The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.



Solution

from collections import deque
class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        ans=[]
        cnt=n #to track the left number of nodes(not visited)
        inDegrees=[0]*n #inDegree means number of connected node except for visited node
        graph=[[] for _ in range(n)]
        
        if n<=2:
            return [i for i in range(n)]
        
        
        for a,b in edges:
            graph[a].append(b)
            graph[b].append(a)
            inDegrees[a]+=1
            inDegrees[b]+=1

        lst= deque([i for i in range(n) if inDegrees[i]==1])
        #make first deque with leaf nodes.
        
        while lst:
            l=len(lst)
            cnt-=l
            if cnt<=2: #the number of answer root node is only 1 or 2.
                break
            
            for _ in range(l):#like BFS searching.
                cur=lst.popleft()
                for nxt in graph[cur]:
                    if inDegrees[nxt]==1:
                        continue
                    
                    inDegrees[nxt]-=1
                    if inDegrees[nxt]==1:
                        lst.append(nxt)

	#finding out root node
        for i,v in enumerate(inDegrees):
            if v!=1:
                ans.append(i)
                cnt-=1
                if cnt==0:
                    break
        
            
        return ans

처음에 감이 안 잡혀서, topic 보고 topological sorting을 처음으로 발견했다. 이 문제를 풀기 전에 GeeksForGeeks에서 topologicla sorting을 먼저 공부해야한다.

Topological sorting은 DFS 방식Kahn's Algorithm 방식 두 가지가 있다. 모두 알아두면 좋을 것 같다.

풀이 과정은 아래 그림을 보면서 insight를 얻을 수 있었다.(그림 크기 조절이 왜 안 될까)

특히 내가 사용한 방식은 inDegree를 이용하는 Kahn's algorithm을 이용하였다. 사실 GeeksForGeeks를 봐도 아이디어가 생각나지 않았다. 그래서 discussion 게시글에서 다음과 같은 한 줄을 읽고 힌트를 얻어서 풀었다.

We are basically trying to delete all leaf nodes at every step. This is very similar to Kahn's Algo or sometimes known as BFS Topological Sort. (ref)

이를 해석하면 다음과 같다. 우리가 찾는 node는 minimum height을 가진 root node이다. 따라서 inDegree가 1이 되는 node, 즉 leaf node를 제거하면서 root node에 가까워질 수 있다.


또한 leetcode 자체 힌트도 도움이 되었다.

How many MHTs can a graph have at most?

나올 수 있는 root node가 하나 아니면 두 개 인 것을 발견할 수 있다.

profile
알고리즘 정리 좀 해볼라고

1개의 댓글

comment-user-thumbnail
2021년 12월 16일

사진 크기 조절하는 법 좀 알려주세요..
< img src="https://images.velog.io/images/jong_p/post/b16292bb-69f8-49c6-9bdb-408fd56ba727/1.jpg" width="160" height="200">

< img src="https://images.velog.io/images/jong_p/post/919be8ee-af26-4da3-9207-b875f79cad8e/2.jpg" width="30%" height="30%">

답글 달기