이 글은 골든래빗 <코딩 테스트 합격자되기 파이썬편>의 10장 써머리입니다.
[집합 기본 개념]: 중복이 없는 원소를 가지는 자료 구조.
상호배타적(disjoint) 집합: 교집합이 없는 관계 -> 그래프 알고리즘에 활용 多
그외 활용 예) 이미지 분할, 도로 네트워크 구성, 최소 신장 트리 알고리즘 구현, 클러스팅 작업 등
표현방법1) 트리형태: 인덱스는 자식노드, 그 값은 부모노드. 루트노드인 경우 인덱스도 루트노드
disjoint 관계라면 한 배열(리스트)에 같이 표현 可
-> union - find 알고리즘 연계
find연산: 특정 노드의 루트 노드 재귀 탐색 -> 루트노드를 찾는 과정으로 최악으론 O(N) 시간복잡도.
효율적으로 하는 방법? -> 경로 압축 이용
union연산: 두 집합을 합치는 것. 두 집합의 루트 노드를 파악하고, 이를 같게 하는 것(둘 중 아무거나 선택)
랭크: 루트 노드로부터 끝 노드 까지의 거리중 가장 긴 거리
합칠 때 랭크기반으로 union 연산을 수행하는게 더 효율적이다. 즉, 랭크가 큰 노드에 작은 랭크의 노드를 합쳐야 한다.
문제 33) 간단한 유니온-파인드 알고리즘 구현하기
union(x, y)로 x와 y가 속한 두 집합을 합치고, find(x)로 x가 속한 집합의 대표 원소를 찾아야 합니다.
k는 노드 개수, operations는 수행할 연산을 담은 리스트입니다. 연산 종류는 2가지입니다.
1. ['u', 1, 2]: 노드 1과 노드 2에 대해 union 연산 수행
2. ['f', 3] 노드 3의 find 연산 수행
루트 노드(초기 노드)의 부모 노드는 자기 자신으로 설정할 때, operatons의 연산을 모두 수행 후 집합의 개수를 반환하는 함수를 구현하세요.
문제랑 주어진 예시가 이해가 안가서 저자의 풀이를 보기로 했다.
def find(parents, x):
# 루트 노드 찾는 함수
if parents[x] == x: # 만약 x의 부모가 자기 자신이면, 즉 x가 루트 노드라면
return x
# 그렇지 않다면 x의 부모를 찾아서 parents[x]에 저장하고,
# 그 부모 노드의 루트 노드를 찾아서 parents[x]에 저장합니다.
parents[x] = find(parents, parents[x])
return parents[x] # parents[x]를 반환합니다.
def union(parents, x, y):
# 두 개의 집합을 합치는 함수
root1 = find(parents, x) # x가 속한 집합의 루트 노드 찾기
root2 = find(parents, y) # y가 속한 집합의 루트 노드 찾기
parents[root2] = root1 # y가 속한 집합을 x가 속한 집합에 합침
def solution(k, operations):
parents = list(range(k)) # 처음에는 각 노드가 자기 자신을 부모로 가지도록 초기화
n = k # 집합의 개수를 저장할 변수, 처음에는 모든 노드가 서로 다른 집합에 있으므로 k
for op in operations: # operations 리스트에 있는 연산들을 하나씩 처리
if op[0] == "u": # 'u' 연산이면
union(parents, op[1], op[2]) # op[1]과 op[2]가 속한 집합을 합칩니다.
elif op[0] == "f": # 'f' 연산이면
find(parents, op[1]) # op[1]이 속한 집합의 루트 노드를 찾습니다.
# 모든 노드의 루트 노드를 찾아서 집합의 개수를 계산
n = len(set(find(parents, i) for i in range(k)))
return n # 집합의 개수를 반환
assert solution(3,[['u',0,1],['u',1,2],['f',2]]) == 1
assert solution(4,[['u',0,1],['u',2,3],['f',0]]) == 2
직접 구현하란 문제는 거의 나올 일은 없겠지만 알고리즘을 공부하란 의미로 만든 문제라고 한다.
문제 34) 폰켓몬
https://school.programmers.co.kr/learn/courses/30/lessons/1845
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
# N = 총 마리수, nums = 폰켓몬 종류번호 담긴 배열
# 목적: N/2마리의 폰켓몬 선택 방법 중, 가장 많은 종류의 폰켓몬 선택한 경우의 개수 return
# idea: set으로 변환한 다음 N개수와 비교해서 값 출력
def solution(nums):
yardstick = len(nums) // 2
return yardstick if yardstick <= len(set(nums)) else len(set(nums))
set개념을 사용하면 매우 가볍게 풀 수 있는 문제이다. 처음엔 문제 그대로 구현하고 조금 더 코드를 짧게 재구성했다.
yardstick도 정의 안하고 쓰면 2줄코드는 되겠지만.. 짧다고 다 좋은게 아니고 return값이 너무 길어지므로 패스
문제 35) 영어 끝말잇기
https://school.programmers.co.kr/learn/courses/30/lessons/12981
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 풀이 미완성
문제 36) 전화번호 목록
https://school.programmers.co.kr/learn/courses/30/lessons/42577
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 풀이 미완성
문제 37) 섬 연결하기
https://school.programmers.co.kr/learn/courses/30/lessons/42861
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 풀이 미완성
'TechStudy > CodingTest' 카테고리의 다른 글
chp16 그리디 (Greedy) (0) | 2024.03.02 |
---|---|
chp11 그래프 (Graph) (1) | 2024.01.13 |
chp9 트리(tree) (4) | 2023.12.21 |
chp8 해시(hash) (1) | 2023.12.13 |
chp6 스택(Stack), chp7 큐(Queue) (4) | 2023.12.07 |