coding/알고리즘,자료구조

트리 부모 찾기 - 질문해서 배운 점들

Jeo 2022. 1. 25. 22:23

백준 11725 트리부모찾기! 스마트하신 항해원분이 BFS로 발표해주시는 걸 듣고 그분의 tip(?!)을 적용해서 DFS로도 풀어보려고 했다.

코드 전 손으로 정리해본 내용은 아래와 같다.

예제들 돌려볼 때는 원하는 출력대로 나오는데 메모리 초과라고 뜬다..!

"백준 메모리초과" 라고 검색해보니 꼭 이 문제는 아니더라도 - 방문처리를 해줘야해요 - 이런 조언들이 있었다.

 

나도 그런 부분에서 잘못하고 있는 걸까? 근데 따로 방문처리할 배열같은 걸 만들 필요가 있을까 모르겠다.

왜냐하면 답변으로 사용할 res 배열을 부모 노드 값으로 채워나가고 있고, 이미 방문했으면 0이 아닐 것인데,

if res[child] == 0: 

이렇게 쓰는 것만으로는 뭔가 새는 부분이 있나..?

 

✔︎ 궁금했던 점

 - 아래의 코드에서 "메모리 초과"가 뜬 원인은 무엇일까?

 - 방문처리를 따로 하지 않아서라면, res 배열에 정보가 할당되었는지로 따져보는 것과 어떤 차이를 갖기 때문일까?

import collections
import sys
sys.setrecursionlimit(10**6)
n = int(sys.stdin.readline())

# 간선 정보들
connect_info = collections.defaultdict(list)
# 결과로 제출할 때 쓸 배열
res = [0] * (n + 1)
# 사용하지 않을 칸을 0이 아닌 값으로 채워두기
res[0] = -1
res[1] = -1

for _ in range(n-1):
    connect = tuple(map(int, sys.stdin.readline().split()))
    connect_info[connect[0]].append(connect[1])
    connect_info[connect[1]].append(connect[0])

def DFS(num):
    if 0 not in res:
        for i in range(2, n+1):
            print(res[i])
        return

    else:
        for child in connect_info[num]:
            if res[child] == 0:
                res[child] = num
                DFS(child)

DFS(1)

 

📝 스마트하신 분한테 질문해서 알게 된 것들

1) 내가 잘못했던 부분 발견

우선 이 분께서도 재귀로 풀어보셨고, 제출이 되었다고 하셨다. 그래서 코드를 공유해주셨는데, 내가 기존에 한 것과 대조해보니까 일단 내가 굳이 필요하지 않은데 작성한 부분이 있다는 것을 알게 되었다. 

이거는 DFS의 종료조건을 써주려고 했던 " if 0 not in res: ~" 부분인데 이게 필요가 없는 부분이었다. 왜냐하면 계속해서 작업할 "else:" 이후의 작업은 connect_info를 다 돌면서 작업을 마치면 어차피 자동 종료될 것이기 때문이었다.

그래서 그 부분을 삭제해서 python3로 제출해봤더니 제출이 되었다..! (+ 근데 pypy로는 안 된다..!)

2) 재귀가 다른 풀이 방식에 비해 더 메모리를 많이 쓴다는 것

stack이나 queue로 풀이 시 메모리 50000kb정도 소모합니다.

재귀로 풀이 시 메모리 150mb 정도 소모합니다. - 이렇게 스마트한 항해원분이 알려주셨다ㅎㅎ

 

얼른 여러 방식의 풀이를 잘 익혀서 내가 풀 수 있는가를 기준으로 방법을 선택하는 것이 아니라, 무엇이 더 효율적인지를 기준으로 풀이 방식을 선택할 수 있는 때가 오면 좋겠다🤓