구간(Interval)을 자료구조로 보기에는 다소 무리가 있지만 코딩 테스트에서 자주 등장하므로 간단히 다루도록 하겠습니다.
구간이란?
구간은 보통 두 개의 원소로 이루어진 배열로 주어지거나, 시작 시점과 종료 시점으로 이루어진 클래스를 사용하기도 합니다.
class Interval(object):
def __init__(self, start, end):
self.start = start
self.end = end
예를 들어, 3에서 시작하고 5에서 끝나는 구간을 배열로 나타내면 다음과 같으며,
interval = [3, 5]
interval[0] # 3
interval[1] # 5
클래스의 인스턴스를 이용해서 나타내면 다음과 같습니다.
interval = Interval(3, 5)
interval.start # 3
interval.end # 5
당연한 얘기이겠지만 구간의 시작점은 구간의 종료점보다 항상 작겠죠?
보통 코딩 테스트 문제에서는 이러한 구간이 여러 개가 들어있는 배열이 입력으로 주어지는 경우가 많습니다.
중첩 구간
여러 개의 구간을 다룰 때는 두 개의 구간 사이에 겹치는 부분이 있는지를 검사해야 할 때가 많은데요. 이 때는 먼저 두 개의 구간 사이에 겹치는 부분이 있는지를 생각해보면 도움이 됩니다.
예를 들어, 아래 두 개의 경우를 보시면 모두 겹치는 부분이 없는데요.
첫 번째 경우에는 A
구간이 시작하는 시점이 B
구간이 끝나는 시점보다 나중에 옵니다.
A: •••••••••
B: •••••••
두 번째 경우에는 B
구간이 시작하는 시점이 A
구간이 끝나는 시점보다 나중에 옵니다.
A: •••••••••
B: •••••••
다시 말해서 아래와 같은 조건을 만족하면 두 개의 구간 사이에는 겹치는 부분이 없을 것입니다.
A.start > B.end or B.start > A.end
논리적으로 반대의 조건에서는 두 개의 구간 사이에 겹치는 부분이 생기겠죠?
A.start < B.end and B.start < A.end
이와 같은 사고 과정없이 바로 위의 공식을 도출하기는 쉽지 않을 수 있어서, 비교적 간단한 반대 경우에 대해서 먼저 생각해보았는데요. 사실 두 개의 구간 사이에 겹치는 부분이 있는 경우는 다음과 같이 상당히 다양합니다.
A: •••••••••
B: •••••••
A: •••••••••
B: •••••••
A: ••••••••••••
B: ••••
A: •••••••••
B: •••••••
A: •••••••••
B: •••••••
A: •••••
B: •••••••••••
한 가지 경우씩 천천히 잘 생각해보시면 모두 우리가 도출한 공식을 만족한다는 것을 깨닫게 될 것입니다.
구간 병합
여러 구간을 다룰 때 또 자주 필요한 작업이 바로 작은 두 개의 구간을 병합하여 더 큰 구간을 만드는 것인데요. 여기서 전제 조건으로 구간 병합이 가능하려면, 두 구간은 겹치거나 적어도 하나의 구간이 끝나는 시점에서 다른 구간이 시작되야 합니다.
이 전제 조건을 만족한다면 병합된 구간은 어렵지 않게 구할 수 있는데요. 두 개의 구간의 시작 시점 중에서 더 작은 것이 병합된 구간의 시작 시점이 되며, 두 개의 구간의 종료 시점 중에서 더 큰 것이 병합된 구간의 종료 시점이 됩니다.
Interval(min(A.start, B.start), max(A.end, B.end))
코딩 테스트 팁
코딩 테스트에서 여러 개의 구간이 입력으로 들어오는 문제를 만나게 되시면 우선 정렬을 고려해보시기 바랍니다.
두 구간의 중첩 여부를 판단할 때 이미 시작 시점을 기준으로 구간이 정렬되어 있으면 중첩되는 구간이 있는지 찾는 게 훨씬 수월해져요.
구간 A와 구간 B가 겹치는지 확인할 때, 정렬로 인해서 A.start < B.start < B.end
는 이미 보장이 되므로 B.start < A.end
만 확인하면 되거든요.
문제에 따라서 종료 시점을 기준으로 정렬하는 게 유리한 경우도 있습니다.
정렬에는 O(nlog(n))
의 시간이 걸리지만, 대신에 훨씬 효율적으로 문제를 해결할 수 있는 경우가 많거든요.
예를 들어, 겹치는 부분이 있는지 확인할 때도, 뒤에 나오는 구간이 앞에 있는 구간이 끝나기 전에 시작하는지만 확인해주면 됩니다.
구간을 다루는 문제는 특히 캘린더나 일정 관리 기능을 제공하는 서비스를 개발하는 회사에서 많이 출제됩니다.
추천 문제
구간의 기초를 다지시는데 아래 문제를 추천드리겠습니다.
위 문제로 기초를 다지셨다면 아래 문제로 실력을 키우실 수 있습니다.