LeetCode Online Judge 题目C# 练习 - Median of Two Sorted Arrays

There are two sorted arrays A and B 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)).

 1         public static double MedianofTwoSortedArrays(int[] A, int[] B)
 2         {
 3             int m = A.Length;
 4             int n = B.Length;
 5 
 6             if (m + n <= 1)
 7             {
 8                 if (m == 0)
 9                     return B[0];
10                 else if (n == 0)
11                     return A[0];
12             }
13             int mid1 = 0, mid2 = 0;
14 
15             //if m + n % 2 == 0, mid2 = mid + 1; else mid1 = mid2 = (m + n) / 2 + 1;
16             mid1 = (m + n) / 2 + (m + n) % 2;
17             mid2 = (m + n) / 2 + 1;
18 
19             int pa = 0, pb = 0, count = 0;
20             double median1 = 0, median2 = 0;
21             
22             //merge two array and keep counting. set median1 and median2 when count = mid1 or mid2 respectively.
23             while (count < mid2)
24             {
25                 if ((pa < m && A[pa] <= B[pb]) || pa >= n)
26                 {
27                     count++;
28                     if (count == mid1)
29                         median1 = A[pa];
30                     if (count == mid2)
31                         median2 = A[pa];
32                     pa++;
33                 }
34                 else
35                 {
36                     count++;
37                     if (count == mid1)
38                         median1 = B[pb];
39                     if (count == mid2)
40                         median2 = B[pb];
41                     pb++;
42                 }
43             }
44 
45             return (median1 + median2) / 2;
46         }

代码分析:

  O(m + n)的做法,把mid1 和 mid2 算出来,如果总长 m + n 是odd, mid1 = mid2, 如果是even, mid2 = mid1 + 1.

  然后pa, pb 指针, merge两个数组同时count, 得到median1和median2后求出median。

  奇怪的是leetcode要求时间复杂度O(log(m+n)),这个O(m+n)的做法居然过了large case.

 1         public static double MedianofTwoSortedArraysOpt(int[] A, int[] B)
 2         {
 3             int t = A.Length + B.Length;
 4             if (t % 2 == 0)
 5             {
 6                 return ((double)FindKth(A, 0, A.Length, B, 0, B.Length, t / 2) +
 7                         (double)FindKth(A, 0, A.Length, B, 0, B.Length, t / 2 + 1)) / 2;
 8             }
 9 
10             return FindKth(A, 0, A.Length, B, 0, B.Length, t / 2 + 1);
11         }
12 
13         public static int FindKth(int[] A, int aoffset, int m, int[] B, int boffset, int n, int k)
14         {
15             //Keep the A is the shorter array.
16             if (m > n) FindKth(B, boffset, n, A, aoffset, m, k);
17 
18             if (m == 0) return B[k - 1];
19             if (k == 1) return Math.Min(A[aoffset], B[boffset]);
20 
21             //set pa and pb pointer
22             int pa = Math.Min(k / 2, m);
23             int pb = k - pa;
24 
25             if (A[aoffset + pa - 1] < B[boffset + pb - 1]) return FindKth(A, aoffset + pa, m - pa, B, boffset, n, k - pa);
26 
27             return FindKth(A, aoffset, m, B, boffset + pb, n - pb, k - pb);
28         }

代码分析:

  这个应该是O(log(k))的做法。因为找两个sorted array 的中位数,其实就是找第K个数的变体,如果m + n 是odd, 那就是找第 (m + n) / 2 个数,如果是even, 那就是找 (m + n) / 2, (m + n) / 2 + 1的平均值。

  这个FindKth()函数也是在mitbbs上看到的,非常牛。用C++写就更简洁了。

  还是想记下这个FindKth()的思路。

  1. 保持A是短的那一个数组,B是长的

  2. 平分k, 一半在A,一半在B (如果A的长度不足K/2,那就pa就指到最后一个)

  3. 如果pa的值 < pb的值,那证明第K个数肯定不会出现在pa之前,递归,把A数组pa之前的砍掉,同理递归砍B数组。(代码中pa - 1是A的index是为了方便,因为题目第K个数,K是从1开始算的)。

  4. 递归到 m == 0 (短的数组用完了) 就返回 B[k - 1], 或者k == 1(找第一个数)就返回min(A第一个数,B第一个数)。(代码中用A[aoffset],因为C#不支持指针,C++里A[0]的完了)。

posted @ 2012-09-26 23:09  ETCOW  阅读(868)  评论(0编辑  收藏  举报