LeetCode刷题笔录 Median Of Two Sorted Arrays

来源:互联网 发布:godaddy域名 七元 编辑:程序博客网 时间:2024/05/08 03:52
    先说临界情况

  1. A为空或者B为空
    直接在非空数组中找第k大的数即可。O(1)
  2. 找最小的数,k==0的情况,也简单,比较两个数组最开头的元素,谁小就是谁
    然后就是比较复杂的情况,假设寻找目标target是下标为k的数。
    那么意味着在排好的数组中,在目标数之前,一共有k个比目标更小的数。
    将k分成两份,一份在A的前端,一份在B的前端。这里其实将k怎么分配是一个可以讨论的问题,但是平分k可以得到平均最快的效果。
    设k = ka + kb,(k是偶数简单,k是奇数的话,剩下那一个随便放在两个数组中哪一个中都可以)

    这里可以列出来我们想要的效果:
    k=1 —-> ka = 1, kb = 1
    k=2 —-> ka = 1, kb = 1
    k=3 —-> ka = 1, kb = 1. [+1,表示还有一个元素,可以随意分配在ka或者kb中,只要不越界]
    k=4 —-> ka = 2, kb = 2
    k=5 —-> ka = 2, kb = 2. [+1]
    已经可以看出来规律了,这个造成了下面代码中比较复杂的部分,这些细节消耗的时间不少啊。

    然后就是主要逻辑

  1. 如果A[ka-1] >= B[kb-1]
    说明在B前端的kb个数中,不可能出现我们要寻找的目标。
    为什么呢?
    假如A一共有m个数,B一共有n个数。
    那么target(下标是k)后面有且只有n + m – 1 – k个数;
    但是B[kb-1]在B中已经排在n – kb个数之前,加上A中的m – ka + 1(A[ka-a]),也就是说在排序后的整体数组中排在B[kb-1]之后的数,至少有n – kb + m – ka + 1 = n + m – k + 1个。
    由于n + m – k + 1 > n + m – k – 1,所以B前端kb个数都不可能是target。
    所以此时可以将问题转化为,在A[0,...,m-1]和B[kb,...,n-1]中,寻找下标为k – kb的数。
  2. 否则,A[ka-1] < B[kb-1]
    同上,可以剔除A前端的ka个数。

这样循环下去,就能以二分的速度找到目标。

这个问题不仅要找到第k大的数,当C是偶数的时候,还要找到第k+1个数,取两者均值。

public class MedianOfTwoSortedArrays {public double findMedianSortedArrays(int A[], int B[], int m, int n) {        // Start typing your Java solution below        // DO NOT write main() function        int lowA =0;int lowB = 0;int highA = m - 1;int highB = n - 1;int k = (m + n) / 2;if((m + n) % 2 == 0){return (findKth(A, B, lowA, highA, lowB, highB, k) + findKth(A, B, lowA, highA, lowB, highB, k + 1)) / 2.0;}elsereturn findKth(A, B, lowA, highA, lowB, highB, k);    }public int findKth(int A[], int B[], int lowA, int highA, int lowB, int highB, int k){int m = highA - lowA + 1;int n = highB - lowB + 1;if (m == 0) return B[lowB + k];if (n == 0)return A[lowA + k];if (k == 0 )return A[lowA] > B[lowB] ? B[lowB] : A[lowA];/*int midA = (lowA + highA) / 2;int midB = (lowB + highB) / 2;if(A[midA] > B[midB]){if((midA + midB + 1) >= k)return findKth(A, B, lowA, midA, lowB, highB, k);elsereturn findKth(A, B, lowA, highA, midB + 1, highB, k - (n / 2 + 1));}else{if((midA + midB + 1) >= k)return findKth(A, B, lowA, highA, lowB, midB, k);elsereturn findKth(A, B, midA + 1, highA, lowB, highB, k - (m / 2 + 1));}*/// Reduce search ranges in A and Bint midA = m * k / (m + n);int midB = k - midA - 1; // Add offset so that imid_A and imid_B index directly into A and B,  respectively midA += lowA;midB += lowB;if (A[midA] > B[midB]) {k -= midB - lowB + 1;highA = midA;lowB = midB + 1;}else {k -= midA - lowA + 1;lowA = midA + 1;highB = midB;}return findKth(A, B, lowA, highA, lowB, highB, k);}}


原创粉丝点击