Median of Two Sorted Arrays

11 篇文章 0 订阅

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5


大概意思就是两个排序好的数组,如果两个数组合并的话找到其中的中位置数

这是我实现的代码有点复杂
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
		int len1 = nums1.length;
		int len2 = nums2.length;

		int sum = len1 + len2;
		int median = sum >> 1;
		int[] numsTemp = null;
		int[] numsTempOr = null;

		int len = 0;

		boolean lastgt = false;
		boolean lastlt = false;

		if (sum % 2 == 0) { // 偶数的时候

			int index2 = len2 >> 1;
			int index = 0;
			numsTemp = nums2;
			numsTempOr = nums1;
			len = len1;
			int medianSub1 = median - 1;

			for (;;) {

				if(numsTemp.length > 0 && index2 < numsTemp.length && index2 > -1)
					index = binarySearch(numsTempOr, numsTemp[index2], len, median - index2);
				else {
					numsTemp = nums1;
					numsTempOr = nums2;
					index2 = len1 >> 1;
					len = len2;
					continue;
				}

				if (index + index2 == median) {
					int index0 = index - 1;
					if(index2 == 0)
						return (numsTemp[index2] + numsTempOr[index0]) / 2.0;
					
					index = binarySearch(numsTempOr, numsTemp[index2 - 1], len, median - index2);

					if (index + index2 - 1 == medianSub1) {
						return (numsTemp[index2] + numsTemp[index2 - 1]) / 2.0;
					} else {
						return (numsTemp[index2] + numsTempOr[index0]) / 2.0;
					}

				} else if (index + index2 == medianSub1) {
					int index0 = index;
					
					if(index2 + 1 == numsTemp.length)
						return (numsTemp[index2] + numsTempOr[index]) / 2.0;
					
					index = binarySearch(numsTempOr, numsTemp[index2 + 1], len, medianSub1 - index2);
					
					if (index + index2 + 1 == median) {
						return (numsTemp[index2] + numsTemp[index2 + 1]) / 2.0;
					} else {
						return (numsTemp[index2] + numsTempOr[index0]) / 2.0;
					}
				} else if (index + index2 > median) {

					if (lastlt == true) {
						numsTemp = nums1;
						numsTempOr = nums2;
						index2 = len1 >> 1;
						len = len2;
						lastlt = false;
					} else {
						index2--;
						lastgt = true;
					}
				} else {

					if (lastgt == true) {
						numsTemp = nums1;
						numsTempOr = nums2;
						index2 = len1 >> 1;
						len = len2;
						lastgt = false;
					} else {
						index2++;
						lastlt = true;
					}
				}
			}

		} else { // 奇数的时候

			int index2 = len2 >> 1;
			int index = 0;
			numsTemp = nums2;
			numsTempOr = nums1;
			len = len1;

			for (;;) {
				
				if(numsTemp.length > 0 && index2 < numsTemp.length && index2 > -1)
					index = binarySearch(numsTempOr, numsTemp[index2], len, median - index2);
				else {
					numsTemp = nums1;
					numsTempOr = nums2;
					index2 = len1 >> 1;
					len = len2;
					continue;
				}
				
				if (index + index2 == median) {

					return numsTemp[index2];

				} else if (index + index2 > median) {

					if (lastlt == true) {
						numsTemp = nums1;
						numsTempOr = nums2;
						index2 = len1 >> 1;
						len = len2;
						lastlt = false;
					} else {
						index2--;
						lastgt = true;
					}
				} else {

					if (lastgt == true) {
						numsTemp = nums1;
						numsTempOr = nums2;
						index2 = len1 >> 1;
						len = len2;
						lastgt = false;
					} else {
						index2++;
						lastlt = true;
					}
				}
			}
		}
	}

	public static int binarySearch(int[] nums, int target, int size, int margin) { // 这个数在数组中前面有多少

		int begin = 0, end = size;
		int temp = 0;

		if(nums.length < 1) {
			return begin;
		}
		
		for (;;) {
			temp = (begin + end) >> 1;

			if (end > begin) {
				if (target > nums[temp]) {
					begin = temp + 1;
				} else if (target == nums[temp]) {
					if(temp == margin) return margin;
					while(nums[temp++] == target) {if(temp - 1 == margin) return margin; if(temp == size) {temp ++; break;}}; 
					return --temp;
				} else {
					end = temp;
				}
			} else {
				return begin;
			}
		}
	}
这是官方的代码
public static double findMedianSortedArrays2(int[] A, int[] B) {
        int m = A.length;
        int n = B.length;
        if (m > n) { // to ensure m<=n
            int[] temp = A; A = B; B = temp;
            int tmp = m; m = n; n = tmp;
        }
        //A是小数组
        int iMin = 0, iMax = m, halfLen = (m + n + 1) >> 1;
        while (iMin <= iMax) {
            int i = (iMin + iMax) >> 1;
            int j = halfLen - i;
            if (i < iMax && B[j-1] > A[i]){
                iMin++; // i is too small, j--, i++
            } else if (i > iMin && B[j] < A[i-1]) {
                iMax--; // i is too big, j++, i--
            } else { // i is perfect
                int maxLeft = 0;
                if (i == 0) { maxLeft = B[j-1]; }
                else if (j == 0) { maxLeft = A[i-1]; }
                else { maxLeft = Math.max(A[i-1], B[j-1]); }
                if ( (m + n) % 2 == 1 ) { return maxLeft; }

                int minRight = 0;
                if (i == m) { minRight = B[j]; }
                else if (j == n) { minRight = A[i]; }
                else { minRight = Math.min(B[j], A[i]); }

                return (maxLeft + minRight) / 2.0;
            }
        }
        return 0.0;
    }
官方的逻辑是这样的:

首先将A数组随机位置i处分成两部分

First let's cut \text{A}A into two parts at a random position ii:

          left_A             |        right_A
    A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]


因为A有m个元素,所以有m+1中分组方式(0~m)

已知:

Since \text{A}A has mm elements, so there are m+1m+1 kinds of cutting (i = 0 \sim mi=0m).

And we know:

\text{len}(\text{left\_A}) = i, \text{len}(\text{right\_A}) = m - ilen(left_A)=i,len(right_A)=mi.


注意:当i=0时,left_A部分是空数组; i=m时,right_A部分是空数组;

Note: when i = 0i=0\text{left\_A}left_A is empty, and when i = mi=m\text{right\_A}right_A is empty.

同理,将B在right_A随机位置j处分成两部分

With the same way, cut \text{B}B into two parts at a random position jj:

          left_B             |        right_B
    B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

将left_A和left_B放入一个区域,同时将right_A和right_B放入另一个区域.并且将这两个区域命名为left_part 和 right_part

Put \text{left\_A}left_A and \text{left\_B}left_B into one set, and put \text{right\_A}right_A and \text{right\_B}right_B into another set. Let's name them \text{left\_part}left_partand \text{right\_part}right_part:

          left_part          |        right_part
    A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]
    B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

当要满足下面两个条件时

If we can ensure:

  1. \text{len}(\text{left\_part}) = \text{len}(\text{right\_part})len(left_part)=len(right_part)
  2. \max(\text{left\_part}) \leq \min(\text{right\_part})max(left_part)min(right_part)

我们将{A, B}两个数组里面所有的元素分成两个相同大小区域时,一个区域的值总是大于另一区域的值,推出

then we divide all elements in \{\text{A}, \text{B}\}{A,B} into two parts with equal length, and one part is always greater than the other. Then

\text{median} = \frac{\text{max}(\text{left}\_\text{part}) + \text{min}(\text{right}\_\text{part})}{2}median=2max(left_part)+min(right_part)

满足这两个条件,只需要满足这两个条件即可:

To ensure these two conditions, we just need to ensure:

  1. i + j = m - i + n - ji+j=mi+nj (or: m - i + n - j + 1mi+nj+1)
    if n \geq mnm, we just need to set:   i=0m, j=m+n+12i  i=0∼m, j=m+n+12−i

  2. \text{B}[j-1] \leq \text{A}[i]B[j1]A[i] and \text{A}[i-1] \leq \text{B}[j]A[i1]B[j]

学习了

right_A
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李文区

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值