num1
, num2
: 입력되는 배열 ()
m
, n
: 2개의 배열 각각의 길이 ()
크기가 각각 m
, n
이면서 정수가 정렬된 상태로 입력되는 2개의 배열이 있을 때, 2개의 정렬된 배열을 합치고 중앙값을 반환하는 문제이다.
단, 시간복잡도가 반드시 이어야만 한다.
중앙값이란,
표본이 가지고 있는 수치를 오름차순 정렬했을 때 가장 중앙에 오는 숫자를 의미하며
1. 표본수가 홀수 → 중앙에 있는 숫자
2. 표본수가 짝수 → 중앙의 좌, 우 2개 숫자의 평균
으로 계산한다.
첫번째 아이디어
+
연산으로 합치기sort()
로 정렬두번째 아이디어 → ✅ 채택
배열을 절반으로 나눠 분할 위치를 결정한다.
num1
, num2
각각 i
, j
위치를 정해 나누기i + j = (m + n + 1) // 2
: 전체 길이의 절반i
감소i
증가2개의 배열 각각 이진 탐색 →
최종 시간복잡도
이므로 조건 를 만족한다.
sort()
로 정렬하고 이진 탐색하기class Solution:
def findMedianSortedArrays(self, nums1: list[int], nums2: list[int]) -> float:
# 길이 비교해 더 짧은 배열을 nums1으로 두기
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
# 길이 저장 변수 정의
m, n = len(nums1), len(nums2)
# 왼쪽, 오른쪽 정의
left, right = 0, m
# 이진탐색 시작
while left <= right:
# nums1은 i, nums2는 j에서 자르기
i = (left + right) // 2
j = (m + n + 1) // 2 - i
# 최솟값, 최댓값 지정
max_left_nums1 = float('-inf') if i == 0 else nums1[i-1]
min_right_nums1 = float('inf') if i == m else nums1[i]
max_left_nums2 = float('-inf') if j == 0 else nums2[j-1]
min_right_nums2 = float('inf') if j == n else nums2[j]
# 잘 분할되었는지 확인
if max_left_nums1 <= min_right_nums2 and max_left_nums2 <= min_right_nums1:
# 홀수라면 중앙값 반환
if (m + n) % 2 == 1:
return max(max_left_nums1, max_left_nums2)
# 짝수라면 평균
else:
return (max(max_left_nums1, max_left_nums2) + min(min_right_nums1, min_right_nums2)) / 2
# 잘 분할 안되었다면 이동
elif max_left_nums1 > min_right_nums2:
right = i - 1
else:
left = i + 1
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
# 두 배열 합치기
nums3 = nums1 + nums2
# 배열 오름차순 정렬
nums3.sort()
# 길이가 짝수면 평균으로 구하기
if len(nums3)%2 == 0:
mid = int(len(nums3) / 2)
total = nums3[mid]+nums3[mid-1]
median = total / 2
# 길이가 홀수면 중앙값 바로 구하기
else:
mid = len(nums3) // 2
median = nums3[mid]
return median