코딩 테스트/백준
[Python] 백준 1931 회의실 배정
위시리
2024. 10. 21. 22:13
문제 분석
- 한 개의 회의실, 사용하고자 하는 팀 N개
- 각 회의 I에 대해 시작시간 & 끝나는 시간이 주어짐
- 각 회의가 겹치지 않고, 회의실을 이용할 수 있는 최대 개수 찾기
- 회의는 시작하면 중단 x
- 회의의 시작시간과 끝나는 시간이 같을 수 있다. == 시작하자마자 끝남
코드 설계
- 이용할 수 있는 최대 회의 수 : 끝나는 시간이 빠른 회의부터 넣으면 많은 회의를 할 수 있음
- 시작시간이 빠른 것부터 정렬하면 언제 끝나는지 모르기 때문에 많이 넣기 힘듦
정답 코드
실패..
import sys
input = sys.stdin.readline
n = int(input())
time = [list(map(int, input().split())) for _ in range(n)]
time.sort()
meeting = []
for i in range(len(time)):
if i == 0 :
meeting.append(time[i])
e = time[i][1] # 종료시간
else : # 회의실을 누가 쓰고 있음 앞서 쓰고 있던 팀이 아직 끝나지 않았다면 다음 회의 순서로 넘어감
if e > time[i][0] : # 끝나는 시간보다 시작시간이 이후이면
continue
else :
meeting.append(time[i])
e = time[i][0]
print(len(meeting))
실행시간이 더 짧은 경우를 고려하지 않음
다른 사람 코드 1
import sys
input = sys.stdin.readline
n = int(input())
meetings = []
for _ in range(n):
start, end = map(int, input().split(" "))
meetings.append((start, end))
meetings.sort(key=lambda x : (x[1], x[0]))
time = 0
cnt = 0
for start_meeting, end_meeting in meetings:
if time <= start_meeting :
time = end_meeting
cnt += 1
print(cnt)
- meeting.sort(key=lambda x : (x[1], x[0]))
- 종료시간을 우선으로 정렬하고, 종료시간이 같은 경우 시작시간을 기준으로 정렬
for _ in range(n): # 대기 회의 개수만큼 반복
start, end = map(int, input().split(" ")) # 띄어쓰기를 기준으로 입력
meetings.append((start, end))
# print(meetings)
# [(1, 4), (3, 5), (0, 6), (5, 7), (3, 8), (5, 9), (6, 10), (8, 11), (8, 12), (2, 13), (12, 14)]
# 종료시간 오름차순 정렬, 시작 시간 오름차순 정렬
meetings.sort(key=lambda x : (x[1], x[0]))
# print(meetings)
# [(1, 4), (3, 5), (0, 6), (5, 7), (3, 8), (5, 9), (6, 10), (8, 11), (8, 12), (2, 13), (12, 14)]
끝나는 시간을 기준으로 정렬해야 최대한 빨리 끝내고 다음 회의를 진행시킴으로 더 많은 회의를 진행할 수 있다.
time = 0 # 끝나는 시간
cnt = 0
for start_meeting, end_meeting in meetings:
if time <= start_meeting : # 끝나고 다서 다음 회의가 시작할 수 있다면
time = end_meeting # 끝나는 시간 갱신
cnt += 1 # 들어간 회의 추가
print(cnt)
2회차 - 2024.10.21
import sys
input = lambda : sys.stdin.readline()
n = int(input())
meeting = []
# 입력
for _ in range(n) :
start, end = map(int, input().split())
meeting.append((start, end))
# 정렬
meeting.sort(key=lambda x : (x[1],x[0]))
# 갯수 세기
cur_end = 0
cnt = 0
for start, end in meeting :
if cur_end <= start :
cur_end = end
cnt += 1
print(cnt)
3회차 - 2025.02.06
현재는 골드 5
pseudo code
회의실을 사용할 수 있는 회의의 최대 개수를 찾아보자
- 최대 개수를 어떻게 구할 수 있을까?
- 시작 시간을 기준으로 정렬하면 언제 끝나는지 확인을 다 해줘야 한다.
/ 회의 시간이 길어진다면 다른 회의를 선택하지 못하는 경우 발생 - 회의 시간이 짧은 순서대로 정렬한다면,
시작/끝 시간을 알지 못한다. 정렬을 했을 때도 다음에 시작하는 적절한 회의를 찾기 힘들다. - 따라서 종료시간을 기준으로 정렬해서 일찍 끝나는 것들부터 한다면, 남는 시간이 길어져 더 많은 수의 회의를 진행할 수 있을 것이다.
- 시작 시간을 기준으로 정렬하면 언제 끝나는지 확인을 다 해줘야 한다.
- pseudo code
- 종료시간을 기준으로 정렬
- 종료 시간을 확인하고, ( 종료 시간 <= 시작시간 ) 인 list를 찾아서 체크
- 체크된 회의의 수 만큼 count
- 찾기 용이하도록 정렬 : 다차원 배열일 때 특정 차원에 대해서 정렬하는 방법 by lamdba
- 종료시간을 기준으로 정렬 → 종료시간이 같을 경우, 시작 시간으로 정렬
# 2차원 배열에서 1차원을 기준으로 정렬
meeting = sorted(meeting, key=lambda x : (x[0], x[1]))
# 2차원 배열에서 2차원을 기준으로 정렬
meeting.sorted(key = lamdba x : (x[1], x[0]))
정답 코드
import sys
input = sys.stdin.readline
n = int(input())
meeting = [list(map(int, input().split())) for _ in range(n)]
meeting = sorted(meeting, key=lambda x : (x[1], x[0]))
ans = 0
# 다음 순서로 진행할 회의 찾기
cur_start, cur_end = 0, 0
for start, end in meeting :
if cur_end <= start :
cur_start = start
cur_end = end
ans += 1
print(ans)
시간 복잡도 (by chatGPT)
🔍 코드의 시간 복잡도 분석
주어진 코드는 회의실 배정 문제를 해결하는 그리디 알고리즘입니다.
이제 코드의 각 부분별로 시간 복잡도를 분석해 보겠습니다.
📌 코드 구조별 시간 복잡도 분석
1️⃣ 입력 처리
n = int(input())
meeting = [list(map(int, input().split())) for _ in range(n)]
- input() 호출: O(1)
- list(map(int, input().split()))는 한 줄을 읽어 int로 변환하므로 O(1)
- 위 과정이 n번 반복되므로 전체 시간 복잡도: O(n)
2️⃣ 정렬
meeting = sorted(meeting, key=lambda x : (x[1], x[0]))
- 정렬 시간 복잡도: sorted()는 **Timsort (O(n log n))**을 사용
- 따라서 이 부분의 시간 복잡도: O(n log n)
3️⃣ 그리디 탐색
cur_start, cur_end = 0, 0
for start, end in meeting :
if cur_end <= start :
cur_start = start
cur_end = end
ans += 1
- for start, end in meeting: O(n)
- if cur_end <= start: O(1) (단순 비교)
- 따라서 전체 루프의 시간 복잡도: O(n)
⏳ 전체 시간 복잡도
각 단계별 시간 복잡도를 정리하면:
- 입력 처리: O(n)
- 정렬: O(n log n)
- 탐색(그리디 선택): O(n)
👉 전체 시간 복잡도는 O(n log n) 🎯
🚀 최적화 여부 검토
- 정렬이 가장 큰 영향을 미치는 단계 (O(n log n)).
- **탐색 부분(O(n))**은 불필요한 연산 없이 최적화되어 있음.
- 즉, 이 코드의 시간 복잡도는 최적이며 더 최적화할 필요 없음. ✅