4. Median of Two Sorted Arrays

  • 겨우 ν’€κΈ°λŠ” ν–ˆλŠ”λ° 아직 upper boundλ₯Ό κ΅¬ν•˜λŠ” 뢀뢄을 λͺ…ν™•ν•˜κ²Œ 이해 λͺ»ν•œκ±° κ°™λ‹€.
  • 기본적인 μ•„μ΄λ””μ–΄λŠ” μ•„λž˜μ™€ κ°™λ‹€.
    • 쀑간값을 ν¬ν•¨ν•˜λŠ” array의 μ ˆλ°˜μ— ν•΄λ‹Ήν•˜λŠ” μœ„μΉ˜λ₯Ό nums1, nums2μ—μ„œ 각각 μ°ΎλŠ”λ‹€.
      • nums1의 쀑간값을 ν¬ν•¨ν•˜λŠ” upper bound pos1 λ₯Ό μ„€μ •ν•œλ‹€
      • nums1[pos1] 값을 κΈ°μ€€μœΌλ‘œ nums2 μ—μ„œ upper bound λ₯Ό μ°ΎλŠ”λ‹€ = pos2
      • 만일 pos1 + pos2 값이 쀑간값을 ν¬ν•¨ν•˜λŠ” μœ„μΉ˜ upperHalf 보닀 μž‘κ±°λ‚˜ 크면 그에 맞좜 수 μžˆλ„λ‘ pos1, pos2λ₯Ό 증가 λ˜λŠ” κ°μ†Œ μ‹œν‚¨λ‹€.
      • 이 λ•Œ μ¦κ°€λŠ” 두 μœ„μΉ˜μ˜ κ°’ 쀑 μž‘μ€ 값을 κ°€μ§„ μͺ½, κ°μ†ŒλŠ” 두 μœ„μΉ˜μ˜ κ°’ 쀑 큰 값을 κ°€μ§„ μͺ½μ— λŒ€ν•΄μ„œ μˆ˜ν–‰ν•œλ‹€.
    • 쀑간값을 κ΅¬ν•œλ‹€.
      • 전체 element의 μˆ˜κ°€ odd인 경우
        • pos1, pos2λŠ” 각 array의 upper boundμ΄λ―€λ‘œ nums1[pos1 - 1], nums2[pos2 - 1] κ°’ 쀑 큰 값을 μ€‘κ°„κ°’μœΌλ‘œ ν•œλ‹€.
      • 전체 element의 μˆ˜κ°€ even인 경우
        • upper boundλŠ” 두 개의 쀑간값 사이에 걸쳐 μžˆλ‹€. λ”°λΌμ„œ upper bound μ΄μ „μ˜ κ°’ ν•˜λ‚˜μ™€ upper bound μœ„μΉ˜μ˜ 값을 평균내어 κ΅¬ν•œλ‹€.
        • 두 array λͺ¨λ‘ upper bound 이전에 elementκ°€ μžˆλŠ” 경우
          • ( max(nums1[pos1 - 1], nums2[pos2 - 1]) + min(nums1[pos1], nums2[pos2]) ) / 2
        • nums1μ—λ§Œ upper bound 이전에 elementκ°€ μžˆλŠ” 경우
          • ( nums1[pos1 - 1] + min(nums1[pos1], nums2[pos2]) ) / 2
        • nums2μ—λ§Œ upper bound 이전에 elementκ°€ μžˆλŠ” 경우
          • ( nums2[pos2 - 1] + min(nums1[pos1], nums2[pos2]) ) / 2
class Solution { public: static constexpr int MIN_NUM = -1000000; static constexpr int MAX_NUM = 1000000; static inline int get(vector<int>& nums, int index, int defVal) { return index >= 0 && index < nums.size() ? nums[index] : defVal; } double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int M = nums1.size(), N = nums2.size(); bool even = (M + N) % 2 == 0; int upperHalf = (M + N + 1) / 2; int pos1 = (M + 1) / 2; auto itr = upper_bound( nums2.begin(), nums2.end(), get(nums1, pos1, MAX_NUM + 1)); int pos2 = itr - nums2.begin(); while (pos1 + pos2 > upperHalf) { auto a = get(nums1, pos1 - 1, MIN_NUM - 1); auto b = get(nums2, pos2 - 1, MIN_NUM - 1); if (a > b) --pos1; else --pos2; } while (pos1 + pos2 < upperHalf) { auto a = get(nums1, pos1, MAX_NUM + 1); auto b = get(nums2, pos2, MAX_NUM + 1); if (a < b) ++pos1; else ++pos2; } if (even) { int a = 0, b = 0; if (pos1 > 0 && pos2 > 0) { a = max( get(nums1, pos1 - 1, MIN_NUM - 1), get(nums2, pos2 - 1, MIN_NUM - 1) ); b = min( get(nums1, pos1, MAX_NUM + 1), get(nums2, pos2, MAX_NUM + 1) ); } else if (pos1 > 0) { a = nums1[pos1 - 1]; b = min( get(nums2, 0, MAX_NUM + 1), get(nums1, pos1, MAX_NUM + 1) ); } else { a = min( get(nums1, 0, MAX_NUM + 1), get(nums2, pos2, MAX_NUM + 1) ); b = nums2[pos2 - 1]; } return (a + b) / 2.0; } else { return max( get(nums1, pos1 - 1, MIN_NUM - 1), get(nums2, pos2 - 1, MIN_NUM - 1) ); } } };