Median of Two Sorted Arrays

来源:互联网 发布:淘宝商家服务社区 编辑:程序博客网 时间:2024/06/16 10:28

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
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小组名称 名称造句 手指名称 笔画名称 名称拼音 闺蜜名称 名称的拼音 颜色名称 战队名称 相册名称 空间名称 qq相册名称 qq名称大全 手机名称 app名称 咖啡店名称 好名称 辅导班名称 的名称 公司的名称 名称英文 isp名称 等级名称 女名称 窗帘店名称 奖励名称 列表名称 备注名称 店名称 任务名称 建材店名称 搞笑的名称 名称是什么 可爱的名称 qq的名称 中国城市名称大全 城市名称大全 群名称大全霸气 名称大全霸气 公司名称大全简单大气 二字公司名称集锦