일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- SQL
- 소프티어
- 시나공
- 공부일지
- 백준 알고리즘
- 정보처리산업기사
- SW봉사
- 백준
- 코틀린
- CJ UNIT
- 문제풀이
- 프로그래머스
- 자바
- 코딩교육봉사
- 백준알고리즘
- 스프링
- BFS
- MYSQL
- python
- 1과목
- java
- kotlin
- softeer
- 코딩봉사
- 파이썬
- programmers
- 알고리즘
- 회고
- C++
- 데이터베이스
- Today
- Total
JIE0025
[BFS][Lv.4] 트리 트리오 중간값 - 파이썬(Python) 본문
문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/68937
문제
✍️ 요약
노드 3개(a,b,c)를 골랐을 때
a-b 사이의 간선 개수
b-c 사이의 간선 개수
c-a 사이의 간선 개수
이 3개의 값중 중간값이 가장 큰 값을 구하는것이 이문제의 목표이다.
📝 빠르게 핵심만 정리하는 트리 개념
✔️ 트리의 특징
- 계층 구조를 갖고 있다.
- 루트 노드가 존재한다 (최상위 노드, 부모가 없음)
- 부모 자식 관계로 이루어져있다.
- 리프노드 (자식이 없는 노드)
- 트리의 깊이 : 루트로부터 특정노드까지의 거리
- 트리는 싸이클이 없다. (특정 노드에서 출발해 다시 특정노드로 돌아올 수 없다.)
✔️ 트리의 지름
트리에서 두 노드를 골랐을 때 가장 큰 거리를 의미함
📝 중간값이란?
수열을 오름차순(증가) 으로 정렬했을때, 중간에 존재하는 값을 의미한다.
* 수가 홀수개 존재하면 : 중간에 위치한 값이 중간값이 된다.
* 수가 짝수개 존재하면 : 중간에 위치한 값이 2개가 발생 -> 두값을 더하고 2로 나눈 값이 중간값이다.
✅ 풀이 과정
문제의 요구사항을 다시 읽어보자
3개의 노드 a,b,c 를 선택해,
a-b / b-c / c-a 의 거리를 구하고, 그 중간값을 찾는다.
이때 가장 큰 중간값을 찾는것이 최종 목표!
단순하게 생각했을 때
가장 큰 중간값을 찾는 노드 3개를 구하려면,
노드와 노드 사이의 거리가 긴 것들을 골라주면 된다.
이때 트리의 지름(특정 노드로부터 가장 큰 거리) 개념을 사용하게 된다.
✍️ 트리의 지름이 1개인 경우
아래 예시 트리 그림을 보자.
2번 노드 > 6번 노드 (거리는 4, 트리의 지름)이다.
거리가 4인 노드의 관계는 2-6외엔 존재하지 않는다.
이때 중간값을 크게 잡기 위한 목적에 맞게
트리의 지름 보다 1 작은 거리인 3에 해당하는 노드를 선택할 수 밖에 없다.
결국 2, 6, 4와 같이 3개를 선택하게 되고
중간값은 무조건 지름-1 이 된다.
✍️ 트리의 지름이 2개 이상인 경우
우린 3개의 거리에서 중간값을 찾고있다.
트리의 지름이 2개 이상이라는것은
이미 3개의 노드에서 경로 2개 (ex : A-B & B-C) 로 가는 경로가 가장 긴 거리라는 의미이다.
그러므로 중간값은 무조건 지름이된다.
✅ 내가 쓴 정답코드
1번 노드로부터 시작해서 BFS를 돌리고, Leaf 노드를 하나 찾는다.
> 첫 선택 노드는 사실 아무거나 선택해도 된다. 일반적으로 1번을 한다.
from collections import deque
def bfs(start, n, graph):
q = deque()
q.append([start,0])
visited = [False] * (n+1)
visited[start] = True
#가장 먼 노드 번호, 가장 먼 노드까지의 거리, 지름의 개수 확인 (1개 or NOT)
farthest_node, farthest_dist, is_farthest_node_unique = start, 0, True
while q:
node, dist = q.popleft()
#현재 노드까지의 거리가, 저장된 가장 먼 노드까지의 거리보다 크면 업데이트 해준다.
if dist > farthest_dist:
farthest_node, farthest_dist, farthest_node_unique = node, dist, True
#현재 노드까지의 거리가, 저장된 가장 먼 노드까지의 거리와 같으면, 지름은 2개 이상 존재하는것
elif dist == farthest_dist:
farthest_node_unique = False
for next in graph[node]:
if not visited[next]:
q.append([next, dist+1])
visited[next] = True
return farthest_node, farthest_dist, farthest_node_unique
def solution(n, edges):
graph = [[] for _ in range(n+1)]
for a, b in edges:
graph[a].append(b)
graph[b].append(a)
# 1: 임의의 노드에서 출발해서 첫번째 leaf 노드를 발견한다.
start_node, _, _ = bfs(1, n, graph)
# 2 : 첫번째 leaf노드로부터 가장 먼 두번째 leaf 노드를 발견한다.
end_node, max_dist, unique = bfs(start_node, n, graph)
if not unique: #트리의 지름이 2개 이상이므로 지름을 리턴해주면 정답
return max_dist
# 3:트리의 지름에 해당하는 값이 1개밖에 없다면,
# 마지막 노드로부터 다시 탐색해서, 진짜 서로 연결된게 지름으로써 Unique한지 체크해준다.
# -> 1개인 경우 <지름 - 1> , 2개 이상이면 <지름>이 정답
answer = 0
_, last_diameter, last_check_unique = bfs(end_node, n, graph)
if last_check_unique:
answer = last_diameter - 1
else:
answer = last_diameter
return answer
references
https://magentino.tistory.com/98
https://developeryuseon.tistory.com/104
'알고리즘 > 프로그래머스' 카테고리의 다른 글
[MySQL][Lv.3] 조건에 맞는 사용자 정보 조회하기 (1) | 2023.11.04 |
---|---|
[MySQL][Lv.1] 경기도에 위치한 식품창고 목록 출력하기 (ISNULL) (0) | 2023.11.04 |
[그리디][lv.2] 귤 고르기 (Java) (1) | 2023.11.01 |
[MYSQL][lv.3] 조회수가 가장 많은 중고거래 게시판의 첨부파일 조회하기 (2) | 2023.10.29 |
[MYSQL][lv.2] 조건에 부합하는 중고거래 상태 조회하기 (0) | 2023.10.29 |