221001_HackerRank : Tree - Top View

Cswยท2022๋…„ 10์›” 1์ผ
0

CodingTest

๋ชฉ๋ก ๋ณด๊ธฐ
3/6
post-custom-banner

๐ŸŒž Tree: Top View

๐ŸšŠ ๋ฌธ์ œ ์„ค๋ช…

  • binary tree์˜ root node์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๊ฐ€ ์ฃผ์–ด์ง€๋ฉด binary tree์˜ top view๋ฅผ printํ•  ๊ฒƒ.
  • top view๋ž€, node์˜ ์œ„์—์„œ ๋ณธ tree๋ฅผ ๋œปํ•จ.

    ์˜ˆ์‹œ 1.
    input : 1 2 5 3 4 6

       1
        \
         2
          \
           5
          /  \
         3    6
          \
           4

    Top View : 1 โ†’ 2 โ†’ 5 โ†’ 6

    ์˜ˆ์‹œ 2.
    input : 1 10 4 3 2 7 5 6 11 15 13 17

            1
              \
               10
              /  \
            4      11
           / \      \
         3    7       15
        /    /  \    /  \  
       2    5    6  13   17

    Top View : 2 โ†’ 3 โ†’ 1 โ†’ 10 โ†’ 11 โ†’ 15 โ†’ 17

์ž…๋ ฅ ์˜ˆ์‹œ

             1 2 5 3 4 6

   1
    \
     2
      \
       5
      /  \
     3    6
      \
       4

์ถœ๋ ฅ ์˜ˆ์‹œ

1 2 5 6

์„ค๋ช…

From the top, only nodes 1, 2, 5, 6 are visible.


๐Ÿšข ๊ธฐ๋ณธ ์ œ๊ณต Code

class Node:
    def __init__(self, info): 
        self.info = info  
        self.left = None  
        self.right = None 
        self.level = None 

    def __str__(self):
        return str(self.info) 

class BinarySearchTree:
    def __init__(self): 
        self.root = None

    def create(self, val):  
        if self.root == None:
            self.root = Node(val)
        else:
            current = self.root
         
            while True:
                if val < current.info:
                    if current.left:
                        current = current.left
                    else:
                        current.left = Node(val)
                        break
                elif val > current.info:
                    if current.right:
                        current = current.right
                    else:
                        current.right = Node(val)
                        break
                else:
                    break

๐Ÿšข Input & Output

tree = BinarySearchTree()
t = int(input())

arr = list(map(int, input().split()))

for i in range(t):
    tree.create(arr[i])

topView(tree.root)

๐Ÿ“‘ Code 1 : BFS

๐Ÿ“Œ Logic ์„ค๋ช…

  • ์œ„์—์„œ ๋ฐ”๋ผ๋ดค์„ ๋•Œ ์ตœ์ดˆ๋กœ ๋ณด์ด๋Š” Node๋งŒ ๋‹ด์•„์•ผ ํ•˜๋Š” ์กฐ๊ฑด์„ ๊ณ ๋ คํ•˜์—ฌ tree์—์„œ์˜ ์ƒํ•˜ level ๊ฐœ๋…์„ ๋น—๋Œ€์–ด ์ขŒ์šฐ level ๊ฐœ๋…์„ depth๋ผ๋Š” ๊ฐ’์œผ๋กœ ํ™œ์šฉ
  • ์ „์ฒด Node๋ฅผ ํƒ์ƒ‰ํ•˜๋ฉด์„œ ์กฐ๊ฑด์— ๋งž๋Š” Node๋งŒ ์ฐพ์•„์•ผ ํ•˜๋ฏ€๋กœ BFS ๊ฐœ๋… ์‚ฌ์šฉ
from collections import deque

def topView(root):
	# ๊ฒฐ๊ณผ๋ฅผ ๋‹ด์„ dict ์ƒ์„ฑ
    #   depth(ํ•ด๋‹น ๋…ธ๋“œ์˜ ์ขŒ์šฐ ํญ์˜ ๋‹จ๊ณ„)์™€ node.info(ํ•ด๋‹น ๋…ธ๋“œ์˜ value)๋ฅผ dict ํ˜•ํƒœ๋กœ ๋‹ด์„ ์˜ˆ์ •
    result = {}
    # queue ์ž๋ฃŒ๊ตฌ์กฐ ์ด์šฉ์„ ์œ„ํ•ด deque ํ•จ์ˆ˜ ์‚ฌ์šฉ
    queue = deque([])
    # root node๋ถ€ํ„ฐ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด queue์— ์ถ”๊ฐ€
    #   ์ขŒ์šฐ ํญ์˜ ๋‹จ๊ณ„(depth)๋ฅผ ์ˆซ์ž๋กœ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ๋…ธ๋“œ๋ฅผ [node, depth] ๋กœ ํ‘œํ˜„
    #   root node๋Š” [root, 0]์œผ๋กœ ํ‘œํ˜„
    queue.append(([root,0]))
    # queue๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ์ง„ํ–‰
    while(queue):
    	# ํ˜„์žฌ level์—์„œ ๊ฐ€์žฅ ์•ž์— ์žˆ๋Š”(depth๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ์€) node๋ฅผ ์„ ํƒ
        current_node = queue.popleft()
        # ๋งŒ์•ฝ, ํ•ด๋‹น depth์˜ node์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ result์— ์—†๋‹ค๋ฉด
        if not current_node[1] in result:
        	# ํ˜„์žฌ ๋…ธ๋“œ์˜ depth:info ๋ฅผ result์— ์ถ”๊ฐ€
            result[current_node[1]] = current_node[0].info
        # ๋งŒ์•ฝ, ํ˜„์žฌ ๋…ธ๋“œ์˜ ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด
        if current_node[0].left:
        	# ๊ทธ ๋…ธ๋“œ๋ฅผ [node, depth] ํ˜•ํƒœ์˜ ์ž๋ฃŒํ˜•์œผ๋กœ queue์— ์ถ”๊ฐ€
            #   ๊ทธ ๋…ธ๋“œ์˜ depth๋Š” ํ˜„์žฌ ๋…ธ๋“œ์˜ depth๋ณด๋‹ค 1์ด ์ž‘์Œ (์™ผ์ชฝ์œผ๋กœ ์ด๋™ํ•˜๋‹ˆ๊นŒ)
            queue.append([current_node[0].left, current_node[1]-1])
        # ๋งŒ์•ฝ, ํ˜„์žฌ ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด
        if current_node[0].right:
            # ๊ทธ ๋…ธ๋“œ๋ฅผ [node, depth] ํ˜•ํƒœ์˜ ์ž๋ฃŒํ˜•์œผ๋กœ queue์— ์ถ”๊ฐ€
            #   ๊ทธ ๋…ธ๋“œ์˜ depth๋Š” ํ˜„์žฌ ๋…ธ๋“œ์˜ depth๋ณด๋‹ค 1์ด ํผ (์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•˜๋‹ˆ๊นŒ)
            queue.append([current_node[0].right, current_node[1]+1])
    # depth ๊ธฐ์ค€์œผ๋กœ dict๋ฅผ ์ •๋ ฌํ•˜๊ธฐ ์œ„ํ•ด items() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉ
    #   depth ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ ์‹œ, top view ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ๋ถ€ํ„ฐ ์ˆœ์„œ๋Œ€๋กœ ์ •๋ ฌ๋จ.
    for depth, value in sorted(result.items()):
        print(str(value), end=" ")

๐Ÿ“‘ Code 2 : DFS

๐Ÿ“Œ Logic ์„ค๋ช…

  • ์œ„์—์„œ ๋ฐ”๋ผ๋ดค์„ ๋•Œ ์ตœ์ดˆ๋กœ ๋ณด์ด๋Š” Node๋งŒ ๋‹ด์•„์•ผ ํ•˜๋Š” ์กฐ๊ฑด์„ ๊ณ ๋ คํ•˜์—ฌ tree์—์„œ์˜ ์ƒํ•˜ level ๊ฐœ๋…์„ ๋น—๋Œ€์–ด ์ขŒ์šฐ level ๊ฐœ๋…์„ depth๋ผ๋Š” ๊ฐ’์œผ๋กœ ํ™œ์šฉ
  • root Node๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ์—ฐ๊ฒฐ๋œ ์ž์‹ Node๋“ค์— ๋Œ€ํ•ด level์„ ๋‚ฎ์ถฐ๊ฐ€๋ฉฐ depth์™€ count(root node๋กœ๋ถ€ํ„ฐ์˜ ์ด๋™ ํšŸ์ˆ˜)๋ฅผ ๊ณ„์‚ฐ โ†’ DFS ๊ฐœ๋…์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 
  • depth๊ฐ€ ๋™์ผํ•œ Node๋“ค์— ๋Œ€ํ•ด์„œ๋Š” count๊ฐ€ ์ ์€ Node๊ฐ€ top view์—์„œ ๋ฐœ๊ฒฌ๋˜๋Š” Node๋ผ๋Š” ์ ์„ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„
# binary tree์˜ ๋ชจ๋“  Node์— ๋Œ€ํ•ด depth(์ขŒ/์šฐ level)์™€ count(์ด๋™ ํšŸ์ˆ˜)๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์กฐ๊ฑด์— ๋งž๋Š” Node๋งŒ ์ถ”์ถœํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑ
def traversal(root, depth, count, temp):
	# root Node๊ฐ€ ์—†์œผ๋ฉด ์ข…๋ฃŒ์‹œํ‚ด
    if root is None:
        return
    # ํ˜„์žฌ ๋…ธ๋“œ์˜ depth๊ฐ€ temp์— ์—†๋‹ค๋ฉด
    if depth not in temp:
    	# ํ˜„์žฌ ๋…ธ๋“œ์˜ depth์™€ [value, count]๋ฅผ dictionary ํ˜•ํƒœ๋กœ temp์— ๋‹ด์Œ
        temp[depth] = [root.info, count]
    # ํ˜„์žฌ ๋…ธ๋“œ์™€ ๋™์ผํ•œ depth๋ฅผ ๊ฐ–๋Š” ๋…ธ๋“œ๊ฐ€ temp์— ์žˆ๋Š” ๊ฒฝ์šฐ,
    #   ํ•ด๋‹น ๋…ธ๋“œ์˜ count๋ณด๋‹ค ํ˜„์žฌ ๋…ธ๋“œ์˜ count๊ฐ€ ๋” ์ž‘๋‹ค๋ฉด
    if count < temp[depth][1]:
    	# ๊ทธ depth๋ฅผ ๊ฐ–๋Š” ๋…ธ๋“œ์˜ ์ •๋ณด๋ฅผ ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ •๋ณด๋กœ ๊ฐฑ์‹ 
        #  ํ•œ๋งˆ๋””๋กœ ์ง€๊ธˆ ๋…ธ๋“œ์˜ depth, info, count๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค ์ด๋ง์ž„
        #    ์™œ๋ƒ๋ฉด, count๊ฐ€ ์ž‘๋‹ค๋Š” ๊ฒƒ์€ ์ด๋™์„ ์ ๊ฒŒํ–ˆ๋‹ค๋Š” ๊ฒƒ์ด๊ณ  ๊ทธ ๋ง์ธ์ฆ‰ 
        #    ์ƒ์œ„ level์— ์œ„์น˜ํ•œ Node์ด๊ธฐ ๋•Œ๋ฌธ์— top view์—์„œ ๋จผ์ € ๋ณด์ธ๋‹ค๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ
        temp[depth] = [root.info, count]
    # ์žฌ๊ท€๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์šฐ์ธก/์ขŒ์ธก ๋ชจ๋‘ ์ „๋ถ€ ๊ณ„์‚ฐ
    #   ์ด๋™ํ•ด์„œ ์ฐพ๋Š” ๊ฒƒ์ธ๋ฐ, ์ด๋™์€ ๋ฌด์กฐ๊ฑด count๊ฐ€ (+1)๋˜๊ณ , 
    #   ์ขŒ/์šฐ ์—ฌ๋ถ€์— ๋”ฐ๋ผ depth๋Š” (-1) ํ˜น์€ (+1)๋จ.
    traversal(root.right, depth + 1, count + 1, temp)
    traversal(root.left, depth - 1, count + 1, temp)

def topView(root):
	# top view๋กœ ๋ฐ”๋ผ๋ณด์•˜์„ ๋•Œ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด์„ dict ์„ ์–ธ
    temp = dict()
    # root Node๋ถ€ํ„ฐ ์ „๋ถ€ ํƒ์ƒ‰ํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ dict์— ๋‹ด์Œ
    traversal(root, 0, 0, temp)
    # depth ๊ธฐ์ค€์œผ๋กœ dict๋ฅผ ์ •๋ ฌํ•˜๊ธฐ ์œ„ํ•ด items() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉ
    #   depth ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ ์‹œ, top view ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ๋ถ€ํ„ฐ ์ˆœ์„œ๋Œ€๋กœ ์ •๋ ฌ๋จ.
    for i in sorted(temp.items()):
        print(i[1][0], end = ' ')
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€