2 분 소요

자료구조를 제외한 라이브러리 최대한 사용하지 않고 문제풀기 (필요하면 직접 코딩)

문제

리트코드 Median of Two Sorted Arrays

문제 풀이 및 회고

문제가 굉장히 어려웠다. 2번까지는 생각이 다 났지만 시간복잡도를 O(log(m+n)) 이어야한다해서 생각이 나질 않았다.

코드(python)

풀이 1. 단순히 합치고 정렬하기

(시간복잡도: (m+n)O(log(m+n)))

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        # 합치고 (O(m+n))
        merged = nums1 + nums2

        # 정렬하기 (O(log(m+n)))
        merged.sort()

        total = len(merged)
        if total % 2 == 1:
            return merged[total//2]
        else:
            return (merged[total//2-1] + merged[total//2])/2

풀이 2. 중앙값이니까 두 리스트 원소를 하나씩 탐색하며 세기

(시간복잡도:O(m+n))

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        m, n = len(nums1), len(nums2)
        idx1, idx2 = 0, 0 # nums1 탐색 idx, nums2 탐색 idx
        result = 0

        mid1, mid2 = 0, 0 # 합쳐진 list가 짝수이면 중앙값은 두개 더 해야함
        for i in range((m+n)//2+1): # 중앙까지 찾기
            mid2 = mid1 # 이전 중앙값 할당
            if idx1 != m and idx2 != n: # 둘다 찾아보는 경우
                if nums1[idx1] < nums2[idx2]:
                    mid1 = nums1[idx1]
                    idx1 += 1
                else:
                    mid1 = nums2[idx2]
                    idx2 += 1
            elif idx1 != m: # idx2는 다 돌았음
                mid1 = nums1[idx1]
                idx1 += 1
            else:
                mid1 = nums2[idx2]
                idx2 += 1
        
        if (m+n)%2 == 1:
            return m1
        else:
            return (m1+m2)/2

문제에서 제시한 시간복잡도로 보아 리스트를 합치지 않고 이진 검색을 해야한다. 예를 들어 m개, n개의 리스트가 있다고 가정하자

$ [nums1[0], nums1[1], ... , nums[m-1]] [nums2[0], nums2[1], ... , nums[n-1]] $

이 두 리스트는 non-decrease 순으로 정렬되어 있기 때문에 두 리스트를 중앙값 대비 나눈다면

$ [nums1[0], nums1[1], ..., nums[a-1]| ... , nums[m-1]] [nums2[0], nums2[1], ..., nums[b-1]| ... , nums[n-1]] $

가 될 수 있다. 여기서 a+b개가 m+n개 중의 절반이므로 a+b = (m+n)//2가 성립한다.

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        m, n = len(nums1), len(nums2)

        if m > n:
            return self.findMedianSortedArrays(nums2, nums1)
        
        low, high = 0, m
        total = m+n

        while low <= high:
            mid1 = (low+high) // 2 # nums1에서 mid idx
            mid2 = (total+1)//2 - mid1 # nums2에서 mid idx

            l1 = nums1[mid1-1] if mid1-1 >= 0 else -float("inf") #mid에서 하나 왼쪽값 
            l2 = nums2[mid2-1] if mid2-1 >= 0 else -float("inf") 
            r1 = nums1[mid1] if mid1 < m else float("inf") # mid 값
            r2 = nums2[mid2] if mid2 < n else float("inf")
            
            if l1 <= r2 and l2 <= r1: # 만약 mid1의 L값(mid-1)이 mid2보다 작거나 같고, mid1 값이 mid2의 L값(mid-1)보다 작거나 같으면 알맞게 찾았음 해당 위치가 중앙값.
                if total %2 == 1:
                    return max(l1, l2)
                else:
                    return (max(l1, l2) + min(r1, r2))/2.0
            elif l1 > r2:
                high = mid1 - 1
            else:
                low = mid1 + 1
        
        return 0

혹은. 근데 아래 풀이는 merged = nums1 + nums2 일 때 시간복잡도가 O(m+n)인거로 아는데(아시는분 댓글 부탁바람) 가장 시간이 빠른 풀이라고 한다…

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        # Merge the arrays into a single sorted array.
        merged = nums1 + nums2

        # Sort the merged array.
        merged.sort()

        # Calculate the total number of elements in the merged array.
        total = len(merged)

        if total % 2 == 1:
            # If the total number of elements is odd, return the middle element as the median.
            return float(merged[total // 2])
        else:
            # If the total number of elements is even, calculate the average of the two middle elements as the median.
            middle1 = merged[total // 2 - 1]
            middle2 = merged[total // 2]
            return (float(middle1) + float(middle2)) / 2.0


궁금한 것들이나 추가 및 수정했으면 좋겠는 거 말해주시면 좋을 거 같아요. 좋은 하루 보내시길 바래요 :)

댓글남기기