|
| 1 | +class Solution: |
| 2 | + def single_place(self, nums, num): |
| 3 | + """returns on which place >= num starts and how many same items""" |
| 4 | + lf, rg = 0, len(nums) - 1 |
| 5 | + md = (lf + rg) // 2 |
| 6 | + while lf <= rg and nums[md] != num: |
| 7 | + if nums[md] <= num: |
| 8 | + lf = md + 1 |
| 9 | + else: |
| 10 | + rg = md - 1 |
| 11 | + md = (lf + rg) // 2 |
| 12 | + |
| 13 | + if nums[md] == num: |
| 14 | + left_step, right_step = 1 >> 11, 1 >> 11 |
| 15 | + lf_sum, rg_sum = 0, 0 |
| 16 | + while left_step and right_step: |
| 17 | + if md - left_step - lf_sum < 0 or nums[md - left_step - lf_sum] != num: |
| 18 | + left_step <<= 1 |
| 19 | + else: |
| 20 | + lf_sum += left_step |
| 21 | + |
| 22 | + if md + right_step + rg_sum >= len(nums) or nums[md + right_step + rg_sum] != num: |
| 23 | + right_step <<= 1 |
| 24 | + else: |
| 25 | + rg_sum += right_step |
| 26 | + |
| 27 | + return [md - lf_sum, rg_sum + lf_sum + 1] |
| 28 | + return [lf, 0] |
| 29 | + |
| 30 | + def place(self, nums1, nums2, num): |
| 31 | + """returns the leftmost and the rightmost place of the element from nums1 in merged list""" |
| 32 | + place1, place2 = self.single_place(nums1, num), self.single_place(nums2, num) |
| 33 | + return [place1[0] + place2[0] + 2, place1[1] + place2[1]] |
| 34 | + |
| 35 | + def find_place(self, nums, other_nums, desired_place): |
| 36 | + lf, rg = 0, len(nums) - 1 |
| 37 | + md = (lf + rg) // 2 |
| 38 | + p = self.place(nums, other_nums, nums[md]) |
| 39 | + while lf <= rg and not (p[0] <= desired_place <= p[0] + p[1]): |
| 40 | + if p[0] > desired_place: |
| 41 | + rg = md - 1 |
| 42 | + else: |
| 43 | + lf = md + 1 |
| 44 | + md = (lf + rg) // 2 |
| 45 | + p = self.place(nums, other_nums, nums[md]) |
| 46 | + return p |
| 47 | + |
| 48 | + def findMedianSortedArrays(self, nums1, nums2, desired_place=None, need_two=None): |
| 49 | + if desired_place is None: |
| 50 | + desired_place = int((len(nums1) + len(nums2)) / 2.0 + 0.5) |
| 51 | + if need_two is None: |
| 52 | + need_two = (len(nums1) + len(nums2)) % 2 == 0 |
| 53 | + |
| 54 | + p = self.find_place(nums1, nums2, desired_place) |
| 55 | + if p[0] <= desired_place < p[0] + p[1]: |
| 56 | + second = nums1[p[0] - 1] |
| 57 | + if need_two: |
| 58 | + second = self.findMedianSortedArrays(nums1, nums2, desired_place=desired_place+1, need_two=False) |
| 59 | + return (nums1[p[0] - 1] + second) / 2. |
| 60 | + |
| 61 | + p = self.find_place(nums2, nums1, desired_place) |
| 62 | + if p[0] <= desired_place < p[0] + p[1]: |
| 63 | + second = nums2[p[0] - 1] |
| 64 | + if need_two: |
| 65 | + second = self.findMedianSortedArrays(nums1, nums2, desired_place=desired_place+1, need_two=False) |
| 66 | + return (nums2[p[0] - 1] + second) / 2. |
| 67 | + |
| 68 | + print("Something went wrong") |
| 69 | + return -1 |
| 70 | + |
| 71 | + |
| 72 | +def main(): |
| 73 | + a = list(map(int, input().split())) |
| 74 | + b = list(map(int, input().split())) |
| 75 | + print(Solution().findMedianSortedArrays(a, b)) |
| 76 | + |
| 77 | + |
| 78 | +if __name__ == "__main__": |
| 79 | + main() |
0 commit comments