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)).
这个题目是非常有名的面试题,
注意leetcode上面对中位数的定义是:
如果合并之后的数组元素个数是奇数,那么中位数就是中间的那位
如果合并之后的数组元素个数是奇数,那么中位数是中间两位的平均数
解题思路有三种
解法一:
使用合并排序,将两个数组重新排序成一个新的数组,这样在O(1)的时间可以找到中位数,排序的时间是O(n+m)
解法二:
先假设数组A的长度为m,数组B的长度为n
1. 先分别找出数组A和数组B的中位数 ma 和 mb,设A[i] = ma , B[j] = mb 然后比较大小
2. 如果 ma < mb, 即A[i] < B[j], 那么中位数一定在A[i..m] 和 B[1..j] 之间, 然后再这个区间再求中位数,递归查找
3. 如果 ma > mb, 即A[i] > B[j],那么中位数一定在A[1..i] 和 B[j..n] 之间,然后再这个区间再求中位数,递归查找
算法比较好理解,但是程序有两点需要注意:
1) 递归的base条件是,当其中一个数组元素个数只剩下小于等于2时,递归结束
2) 每次递归时,在两个数组中选择除去的元素一定要相等。比如说A数组减去两个元素,那么B数组也要减去两个,这样剩下的区间的中位数和原来的中位数是一样的
程序如下: 这个代码过了leetcode的所有case,算是bug free了。
/** * find median of two sorted array, the values in array may same * * <p> * The algorithm are: * </p> * <ol> * <li>Calculate the medians m1 and m2 of the input arrays A and B * respectively.</li> * <li>If m1 is less than m2, then the median located between * A[m-index(m1)..m] and B[0..index(m2)], index(m1),index(m2) are the index * of array A and B,repeat finding median recrusively</li> * <li>If m1 is greater than m2, then the median located between * A[0..index(m1)] and B[n-index(m2)..n] ,repeat finding median recrusively</li> * </ol> * */ static class FindMedian1 { public static double medianSelect(int[] A, int[] B) { if (A == null && B == null) { return -1; } else if ((A == null || A.length == 0) && B.length != 0) { return B.length % 2 == 1 ? B[(B.length - 1) / 2] : (B[(B.length - 1) / 2] + B[(B.length - 1) / 2 + 1]) / 2.0; } else if (B == null || B.length == 0 && A.length != 0) { return A.length % 2 == 1 ? A[(A.length - 1) / 2] : (A[(A.length - 1) / 2] + A[(A.length - 1) / 2 + 1]) / 2.0; } return findMedian(A, 0, A.length - 1, B, 0, B.length - 1); } public static double findMedian(int[] A, int p, int r, int[] B, int l, int h) { if (p == r) {// only one element left to compare return findMedianBaseCase1(A[p], B, l, h); } else if (l == h) { return findMedianBaseCase1(B[l], A, p, r); } else if (r == p + 1) { return findMedianBaseCase2(A[p], A[r], B, l, h); } else if (h == l + 1) { return findMedianBaseCase2(B[l], B[h], A, p, r); } int medA = (p + r) / 2; int medB = (l + h) / 2; if (A[medA] <= B[medB]) { int k = 0; if ((r - p + 1) % 2 == 0) { k = Math.min(medA - 1, h - medB - 1); } else { k = Math.min(medA, h - medB - 1); } k = k == 0 ? 1 : k; return findMedian(A, p + k, r, B, l, h - k); } else { int k = 0; if ((h - l + 1) % 2 == 0) { k = Math.min(medB - 1, r - medA - 1); } else { k = Math.min(medB, r - medA - 1); } k = k == 0 ? 1 : k; return findMedian(A, p, r - k, B, l + k, h); } } public static double findMedianBaseCase1(int med, int[] A, int p, int r) { if (r == p) { return (med + A[p]) / 2.0; } if (med == A[(r + p) / 2]) { return med; } else if (med < A[(r + p) / 2]) { if ((r - p + 1) % 2 == 0) { return A[(r + p) / 2]; } else { return (Math.max(med, A[(r + p) / 2 - 1]) + A[(r + p) / 2]) / 2.0; } } else {// if(med > A[(r+p)/2]) if ((r - p + 1) % 2 == 1) { return (A[(r + p) / 2] + Math.min(med, A[(r + p) / 2 + 1])) / 2.0; } else { return med < A[(r + p) / 2 + 1] ? med : A[(r + p) / 2 + 1]; } } } // med2 > med1 by default public static double findMedianBaseCase2(int med1, int med2, int[] A, int p, int r) { int medA = (r + p) / 2; if (r == p + 1) { if (med1 > A[p]) { if (med2 < A[r]) { return (med1 + med2) / 2.0; } else { return (med1 + A[r]) / 2.0; } } else if (med2 > A[r]) { return (A[r] + A[p]) / 2.0; } else { return (med2 + A[p]) / 2.0; } } if ((r - p + 1) % 2 == 0) { if (med2 < A[medA]) { return (Math.max(med2, A[medA - 1]) + A[medA]) / 2.0; } else if (med1 > A[medA]) { if (med2 < A[medA + 1]) { return (med1 + med2) / 2.0; } else {// med2 > A[medA+1] return (Math.min(med1, A[medA + 2]) + A[medA + 1]) / 2.0; } } else { return (A[medA] + Math.min(med2, A[medA + 1])) / 2.0; } } else { if (med1 > A[medA]) { return Math.min(A[medA + 1], med1); } else if (med2 < A[medA]) { return Math.max(med2, A[medA - 1]); } else { return A[medA]; } } } }
相关推荐
4. **排序与查找**:快速排序、归并排序、二分查找等经典算法经常出现在LeetCode题目中,比如"Median of Two Sorted Arrays"要求找到两个有序数组的中位数,这需要灵活运用二分查找。 5. **递归与迭代**:如"Binary...
- **寻找数组中的中位数(Median of Two Sorted Arrays)**: 在两个排序数组中找到中位数。 - **快速选择算法(Kth Largest Element)**: 选择一个无序数组中的第k大的元素。 #### 二分搜索扩展 - **二分搜索变体(First...
寻找两个有序数组的中位数 困难 Algorithm 5 最长回文子串 中等 Algorithm 6 Z字形变换 中等 Algorithm 7 整数翻转 简单 Algorithm 8 字符串转换整数 (atoi) 中等 Algorithm 9 回文数 简单 Algorithm 10 正则表达式...
3. **链表**:链表问题测试了对指针和节点操作的理解,比如反转链表、合并两个有序链表等。"两链表的第一个公共节点"(Intersection of Two Linked Lists)就是一个实例。 4. **二叉树**:二叉树结构常用于搜索和...
将有序数组转换为二叉搜索树 第 9 周问题列表: 杰森 0277 找名人 0136 单号 GG 0101 对称树 0329 矩阵中最长的递增路径 最大限度 0328 奇偶链表 0141 链表循环 AY 0038 数数说 0150 评估反向波兰符号 星期日 0118 ...
- **链表**:链表操作问题,如"反转链表"(Reverse Linked List)和"合并两个有序链表"(Merge Two Sorted Lists)。 - **栈与队列**:"有效的括号"(Valid Parentheses)展示了栈的应用,"最小生成树"(Kruskal's...
例如,“寻找两个有序数组的中位数”可以通过双指针或二分查找法解决,而“岛屿数量”则可能需要我们用DFS或BFS来遍历二维网格。 3. **动态规划**:动态规划是一种解决复杂问题的有效方法,如“最长公共子序列”、...
LeetCode中的这类问题涵盖了排序、查找、反转等操作,如“两数之和”(Two Sum)、“旋转数组”(Rotate Array)和“合并两个有序链表”(Merge Two Sorted Lists)。 2. **栈和队列**:这两种线性结构在处理逆序...