leetcode |4. Median of Two Sorted Arrays(分治/二分查找)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mike_learns_to_rock/article/details/88809097

解法1 排序

  • 假排序,只排到前一半的数即可。
  • 时间复杂度:O(m + n)
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int l1 = nums1.length;
        int l2 = nums2.length;
        int total = l1 + l2;
        int[] virtual = new int[total];
        int n1 = 0;
        int n2 = 0;
        int index = 0;
        while (n1 < l1 && n2 < l2 && index <= total/2) {
            if (nums1[n1] < nums2[n2]) {
                virtual[index] = nums1[n1];
                n1++;
            } else {
                virtual[index] = nums2[n2];
                n2++;
            }
            index++;
        }
        
        while (n1 < l1 && index <= total/2) {
             virtual[index++] = nums1[n1++];
        }
    
        while (n2 < l2 && index <= total/2) {
             virtual[index++] = nums2[n2++];
        }
     
        if ((total & 1) == 1 ) {
            return virtual[total/2];
        } else {
            return (double)virtual[total/2 - 1] / 2 + (double)virtual[total/2] / 2;
        }
    }

解法2 分治

  • 时间复杂度O(log(m+n))
  • 转换为findKth问题,这里的K从0开始,表示offset
  • A和B长度分别为m和n,比较A[k/2] 和 B[k/2]的大小(也可以比较A[m * k / (m + n)]和B[n * k / (m + n)])
  • A[k/2] < B[k/2], 转换为从A[k/2 + 1, …] 和B数组寻找第k/2大的数
  • A[k/2] > B[k/2],转换为从B[k/2 + 1, …] 和A数组寻找第k/2大的数
  • A[k/2] == B[k/2],得到答案
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int total = nums1.length + nums2.length;
        if (total % 2 == 0) {
            return (double)findKth(nums1, 0, nums2, 0, total / 2 - 1) / 2 +
                    (double)findKth(nums1, 0, nums2, 0, total / 2) / 2;
        } else {
            return findKth(nums1, 0, nums2, 0, total / 2);
        }
    }

    // k从0开始,第k小的数
    private int findKth(int[] nums1, int start1, int[] nums2, int start2, int k) {
        if (nums1.length - start1 > nums2.length - start2) {
            return findKth(nums2, start2, nums1, start1, k);
        }
        if (nums1.length - 1 < start1) {
            return nums2[start2 + k];
        }
        if (k == 0) {
            return Math.min(nums1[start1], nums2[start2]);
        }

        // k1 + 1 + k2 + 1 == k + 1
        int offset1 = 0;
        if (k / 2 < nums1.length - 1 - start1) {
            offset1 = k / 2;
        } else {
            offset1 = nums1.length - 1 - start1;
        }
        int offset2 = k - 1 - offset1;
        if (nums1[offset1 + start1] < nums2[offset2 + start2]) {
            return findKth(nums1, start1 + offset1 + 1, nums2, start2, k - offset1 - 1);
        } else  if (nums1[offset1 + start1] > nums2[offset2 + start2]) {
            return findKth(nums1, start1, nums2, start2 + offset2 + 1, k - offset2 - 1);
        } else {
            return nums1[start1 + offset1];
        }
    }

解法3 二分查找

  • 时间复杂度 O(log(m+n))
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        if (len1 > len2) return findMedianSortedArrays(nums2, nums1);
        int k = (len1 + len2 + 1) / 2;
        int l = 0;
        int r = len1;
        //find the m1 so that nums1[m1] >= nums2[m2 - 1]
        while(l < r){
            int m1 = l + (r - l) / 2;
            int m2 = k - m1;
            if (nums1[m1] < nums2[m2 - 1]){
                l = m1 + 1;
            } else {
                r = m1;
            }
        }
        int m1 = l;
        int m2 = k - l;
        int c1 = Math.max(m1 <= 0 ? Integer.MIN_VALUE : nums1[m1 - 1],
                         m2 <= 0? Integer.MIN_VALUE: nums2[m2 - 1]);
        if ((len1 + len2) % 2 ==1) return c1;
        int c2 = Math.min(m1 >= len1 ? Integer.MAX_VALUE : nums1[m1],
                         m2 >= len2 ? Integer.MAX_VALUE: nums2[m2]);
        return (c1 + c2) / 2.0;
    }

猜你喜欢

转载自blog.csdn.net/mike_learns_to_rock/article/details/88809097