서류 심사와 면접 시험을 기준으로 신입 사원을 선발하려고 한다.
지원자는 (서류 심사 성적, 면접 시험 성적) 두 가지 기준으로 평가되며, 두 성적 중 하나라도 다른 지원자보다 떨어지지 않는 경우에만 선발된다.
즉, 어떤 지원자 A가 지원자 B보다 두 성적 모두 낮으면 A는 선발되지 않는다.
이때, 선발할 수 있는 최대 지원자 수를 구하는 프로그램을 작성하라.
T가 주어진다.N (1 \leq N \leq 100000)이 주어진다.N개의 줄에 각 지원자의 (서류 심사 성적, 면접 시험 성적)이 주어진다. (1등이 가장 높은 순위)각 테스트 케이스마다 선발할 수 있는 최대 지원자 수를 출력한다.
처음에는 이중 반복문을 사용하여 모든 지원자들의 서류 및 면접 성적을 비교하면서 선발 여부를 결정하려 했다.
즉, 각 지원자를 기준으로 나머지 지원자들과 비교하여, 자신보다 두 성적 모두 낮은 지원자가 존재하는지 확인하는 방식이었다.
T = int(input())
res = []
for _ in range(T):
N = int(input())
a = []
cnt = N
for i in range(N):
a.append(tuple(map(int, input().split())))
a.sort(key=lambda x: -x[0]) # 서류 성적 기준 내림차순 정렬
for i in range(N-1):
for j in range(i+1, N):
if a[i][1] > a[j][1]: # 면접 성적도 낮으면 탈락
cnt -= 1
break
res.append(cnt)
for i in res:
print(i)
O(N^2)의 시간 복잡도가 발생함.N의 최대값이 100,000이므로, 최악의 경우 100,000^2 = 10^10 연산이 발생하여 시간 초과가 발생함.시간 초과를 해결하기 위해 이중 반복문을 제거하고, 한 번의 순회로 해결할 방법을 고민했다.
O(N log N) + O(N) = O(N log N)로 해결 가능!import sys
input = sys.stdin.readline
T = int(input())
res = []
for _ in range(T):
N = int(input())
a = []
for i in range(N):
a.append(tuple(map(int, input().split())))
a.sort() # 서류 성적 기준 오름차순 정렬
cnt = 1 # 첫 번째 지원자는 무조건 선발
min_interview = a[0][1]
for i in range(1, N):
if a[i][1] < min_interview: # 면접 성적이 현재까지의 최소보다 낮으면 선발 가능
min_interview = a[i][1]
cnt += 1
res.append(cnt)
print("\n".join(map(str, res)))
| 접근 방식 | 시간 복잡도 | 이유 |
|---|---|---|
| 기존 코드 | O(N^2) | 모든 지원자를 비교 |
| 개선된 코드 | O(N log N) | 정렬 + 1회 순회 |
O(N^2)의 시간 복잡도가 발생했음.O(N log N) + O(N) = O(N log N)으로 줄어듦!O(N^2)로 인해 시간 초과가 발생함.O(N log N)으로 해결 가능함!