[PRO] 길 찾기 연습

천호영·2022년 9월 3일
0

알고리즘

목록 보기
51/100
post-thumbnail

약 50분의 풀이시간 끝에 처음 작성한 풀이는 다음과 같다.
이때, 대부분은 시간초과가 나고, 런타임에러도 몇 개 같이 나왔다.

런타임에러의 원인은 sys.setrecutionlimit(10**6)을 적지 않아서였다.
재귀를 이용할 때 항상 생각하자.

node_num_info = None

class TreeNode:
    def __init__(self, node_num, left, right):
        self.node_num = node_num
        self.left = left
        self.right = right
        
        
def tree_make(left_x, right_x, upper_y):
    '''
    left_x 초과 right_x 미만인 x범위이고 upper_y 미만인 y범위의 서브트리 반환
    '''
    
    global node_num_info
    
    # 시간초과 날듯
    for y in reversed(range(upper_y)):
        for x in range(left_x+1, right_x):
            node_num = node_num_info[x][y]
            if node_num:
                new_x, new_y = x,y
                left = tree_make(left_x, new_x, new_y)
                right = tree_make(new_x, right_x, new_y)
                return TreeNode(node_num, left, right)
            
    return None # 해당 범위의 노드가 없으면 None으로 반환


def preorder(node, preorder_list):
    preorder_list.append(node.node_num)
    if node.left:
        preorder(node.left, preorder_list)
    if node.right:
        preorder(node.right, preorder_list)

        
def postorder(node, postorder_list):
    if node.left:
        postorder(node.left, postorder_list)
    if node.right:
        postorder(node.right, postorder_list)
    postorder_list.append(node.node_num)

    
def solution(nodeinfo):
    global node_num_info
    answer = [[]]
    
    min_x = min(x for x,y in nodeinfo)
    max_x = max(x for x,y in nodeinfo)
    max_y = max(y for x,y in nodeinfo)
    
    node_num_info = [[0]*(max_y+1) for _ in range(max_x+1)]
    for i,(x, y) in enumerate(nodeinfo):
        node_num_info[x][y] = i+1
    # 트리 제작
    root_tree = tree_make(min_x-1, max_x+1, max_y+1)
    
    now_node = root_tree
    preorder_list = []
    preorder(now_node, preorder_list)
    
    now_node = root_tree
    postorder_list = []
    postorder(now_node, postorder_list)
    
    return [preorder_list, postorder_list]

이후 50분의 추가 고민(with 다른 풀이 참조) 이후 정답처리된 코드는 다음과 같다.

핵심은 for문에서 존재하는 x,y좌표에 대해서만 순회하는 것이다.
x,y 범위에 대해 모두 for문을 돌게 되면 10000*10000인데, 존재하는 x,y좌표만 돌면 10000이기 때문이다.

from collections import defaultdict
import sys
sys.setrecursionlimit(10 ** 6) # !런타임 에러 방지

node_num_info = None
reversed_y_list = None

class TreeNode:
    def __init__(self, node_num, left, right):
        self.node_num = node_num
        self.left = left
        self.right = right
        
        
def tree_make(left_x, right_x, upper_y):
    '''
    left_x 초과 right_x 미만인 x범위이고 upper_y 미만인 y범위의 서브트리 반환
    '''
    
    global node_num_info, reversed_y_list
    
    # 시간초과 나던 곳
    for y in reversed_y_list: # !존재하는 y만 돌아야됨
        if y < upper_y:
            for x, node_num in node_num_info[y]: # !존재하는 x만 돌아야됨
                if left_x < x < right_x:
                    new_x, new_y = x,y
                    left = tree_make(left_x, new_x, new_y)
                    right = tree_make(new_x, right_x, new_y)
                    return TreeNode(node_num, left, right)
            
    return None # 해당 범위의 노드가 없으면 None으로 반환


def preorder(node, preorder_list):
    preorder_list.append(node.node_num)
    if node.left:
        preorder(node.left, preorder_list)
    if node.right:
        preorder(node.right, preorder_list)

        
def postorder(node, postorder_list):
    if node.left:
        postorder(node.left, postorder_list)
    if node.right:
        postorder(node.right, postorder_list)
    postorder_list.append(node.node_num)

    
def solution(nodeinfo):
    global node_num_info
    global reversed_y_list
    
    min_x = min(x for x,y in nodeinfo)
    max_x = max(x for x,y in nodeinfo)
    max_y = max(y for x,y in nodeinfo)
    reversed_y_list = list(sorted(set(y for x,y in nodeinfo), reverse=True))
    
    node_num_info = defaultdict(list)
    for i,(x, y) in enumerate(nodeinfo):
        node_num_info[y].append((x,i+1)) # x좌표, 노드 번호
        
    # 트리 제작
    root_node = tree_make(min_x-1, max_x+1, max_y+1)
    
    now_node = root_node
    preorder_list = []
    preorder(now_node, preorder_list)
    
    now_node = root_node
    postorder_list = []
    postorder(now_node, postorder_list)
    
    return [preorder_list, postorder_list]
profile
성장!

0개의 댓글