LeetCode OJ4 Median of Two Sorted Arrays 小结
来源:互联网 发布:美国原油库存eia数据 编辑:程序博客网 时间:2024/06/07 20:35
Median of Two Sorted Arrays
问题描述
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)).
解题思路
一开始想到的思路是: 将数组归并排序, 然后对排序成一个数组的序列, 进行二分查找, 时间复杂度 为
后来, 实现想不出方法之后, 无奈之下, 参考了大神门的源码,得到启发。
我们可以求数组的第K个元素!!!
我们可以取两个排序数组的中值, 进行比较。并计长的数组为a, 短的数组为b, 分别取他们的[k / 2] 处的值。 如果 a 中的值, 小于 b 中的值,表明 a 中的值之前的部分 不是我们 所求的第 K 个元素的范围, 因而由此可以缩小寻找范围!!!
AC code
class Solution {public: // 此处的 k 以 1 开始计数 double findMed(int a[], int m, int b[], int n, int k) { if (m < n) return findMed(b, n, a, m, k); if (n == 0) return a[k - 1]; if (k == 1) return min(a[0], b[0]); int pb = min(k/2, n); int pa = k - pb; if (a[pa - 1] < b[pb - 1]) return findMed(a + pa, m - pa, b, n, k - pa); else if (a[pa - 1] > b[pb - 1]) return findMed(a, m, b + pb, n - pb, k - pb); else return a[pa - 1]; } double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int k = (nums1.size() + nums2.size()); if (k & 0x1 != 0) return findMed(&nums1[0], nums1.size(), &nums2[0], nums2.size(), k / 2 + 1); else return findMed(&nums1[0], nums1.size(), &nums2[0], nums2.size(), k / 2) / 2 + findMed(&nums1[0], nums1.size(), &nums2[0], nums2.size(), k / 2 + 1) / 2; }};
大神们的代码
demo 1
share my o(log(min(m,n)) solution with explanation
翻译下大神的思路, 将两个数组的元素分成数量相等的两部分,找出符合这种要求的分割点 i(二分法);求出 中值
Given a sorted array A with length m, we can split it into two part:{ A[0], A[1], ... , A[i - 1] } | { A[i], A[i + 1], ... , A[m - 1] }All elements in right part are greater than elements in left part.The left part has "i" elements, and right part has "m - i" elements.There are "m + 1" kinds of splits. (i = 0 ~ m)When i = 0, the left part has "0" elements, right part has "m" elements.When i = m, the left part has "m" elements, right part has "0" elements.For array B, we can split it with the same way:{ B[0], B[1], ... , B[j - 1] } | { B[j], B[j + 1], ... , B[n - 1] }The left part has "j" elements, and right part has "n - j" elements.Put A's left part and B's left part into one set. (Let's name this set "LeftPart")Put A's right part and B's right part into one set. (Let's name this set"RightPart") LeftPart | RightPart { 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) LeftPart's length == RightPart's length (or RightPart's length + 1) 2) All elements in RightPart are greater than elements in LeftPart.then we split all elements in {A, B} into two parts with eqaul length, and one part isalways greater than the other part. Then the median can be easily found.To ensure these two condition, we just need to ensure: (1) i + j == m - i + n - j (or: m - i + n - j + 1) if n >= m, we just need to set: i = 0 ~ m, j = (m + n + 1) / 2 - i (2) B[j - 1] <= A[i] and A[i - 1] <= B[j] considering edge values, we need to ensure: (j == 0 or i == m or B[j - 1] <= A[i]) and (i == 0 or j == n or A[i - 1] <= B[j])So, all we need to do is: Search i from 0 to m, to find an object "i" to meet condition (1) and (2) above.And we can do this search by binary search. How?If B[j0 - 1] > A[i0], then the object "ix" can't be in [0, i0]. Why? Because if ix < i0, then jx = (m + n + 1) / 2 - ix > j0, then B[jx - 1] >= B[j0 - 1] > A[i0] >= A[ix]. This violates the condition (2). So ix can't be less than i0.And if A[i0 - 1] > B[j0], then the object "ix" can't be in [i0, m].So we can do the binary search following steps described below:1. set imin, imax = 0, m, then start searching in [imin, imax]2. i = (imin + imax) / 2; j = (m + n + 1) / 2 - i3. if B[j - 1] > A[i]: continue searching in [i + 1, imax] elif A[i - 1] > B[j]: continue searching in [imin, i - 1] else: bingo! this is our object "i"When the object i is found, the median is:max(A[i - 1], B[j - 1]) (when m + n is odd)or (max(A[i - 1], B[j - 1]) + min(A[i], B[j])) / 2 (when m + n is even)Below is the accepted code:def median(A, B): m, n = len(A), len(B) if m > n: A, B, m, n = B, A, n, m imin, imax, half_len = 0, m, (m + n + 1) / 2 while imin <= imax: i = (imin + imax) / 2 j = half_len - i if j > 0 and i < m and B[j - 1] > A[i]: imin = i + 1 elif i > 0 and j < n and A[i - 1] > B[j]: imax = i - 1 else: if i == 0: num1 = B[j - 1] elif j == 0: num1 = A[i - 1] else: num1 = max(A[i - 1], B[j - 1]) if (m + n) % 2 == 1: return num1 if i == m: num2 = B[j] elif j == n: num2 = A[i] else: num2 = min(A[i], B[j]) return (num1 + num2) / 2.0
C++ version
class Solution {public: double findMedianSortedArrays(int A[], int m, int B[], int n) { if (m > n) return findMedianSortedArrays(B, n, A, m); int minidx = 0, maxidx = m, i, j, num1, mid = (m + n + 1) >> 1,num2; while (minidx <= maxidx) { i = (minidx + maxidx) >> 1; j = mid - i; if (i<m && j>0 && B[j-1] > A[i]) minidx = i + 1; else if (i>0 && j<n && B[j] < A[i-1]) maxidx = i - 1; else { if (i == 0) num1 = B[j-1]; else if (j == 0) num1 = A[i - 1]; else num1 = max(A[i-1],B[j-1]); break; } } if (((m + n) & 1)) return num1; if (i == m) num2 = B[j]; else if (j == n) num2 = A[i]; else num2 = min(A[i],B[j]); return (num1 + num2) / 2.; }};
demo2
Very concise O(log(min(M,N))) iterative solution with detailed explanation
大神思路: 设计虚拟位置,
由于要求左右两边保持平衡, 相等, 或者仅相差一个元素, 可以得到 1,2 两个数组之间的联系, 基于此对 较短的数组进行二分查找即可!!!
本质上, demo1, demo2 的思想是一致的!!!
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int N1 = nums1.size(); int N2 = nums2.size(); if (N1 < N2) return findMedianSortedArrays(nums2, nums1); // Make sure A2 is the shorter one. if (N2 == 0) return ((double)nums1[(N1-1)/2] + (double)nums1[N1/2])/2; // If A2 is empty int lo = 0, hi = N2 * 2; while (lo <= hi) { int mid2 = (lo + hi) / 2; // Try Cut 2 int mid1 = N1 + N2 - mid2; // Calculate Cut 1 accordingly double L1 = (mid1 == 0) ? INT_MIN : nums1[(mid1-1)/2]; // Get L1, R1, L2, R2 respectively double L2 = (mid2 == 0) ? INT_MIN : nums2[(mid2-1)/2]; double R1 = (mid1 == N1 * 2) ? INT_MAX : nums1[(mid1)/2]; double R2 = (mid2 == N2 * 2) ? INT_MAX : nums2[(mid2)/2]; if (L1 > R2) lo = mid2 + 1; // A1's lower half is too big; need to move C1 left (C2 right) else if (L2 > R1) hi = mid2 - 1; // A2's lower half too big; need to move C2 left. else return (max(L1,L2) + min(R1, R2)) / 2; // Otherwise, that's the right cut. } return -1;}
demo3
share my simple O(log(m+n)) solution for your reference
这个思路, 就是我们参考的那个思路,一次砍掉将近 1 / 4 的数据
通过主定理很容易看出, 时间复杂度为
ps: 这里的 K 从 1 开始计数
class Solution {public: int getkth(int s[], int m, int l[], int n, int k){ // let m <= n if (m > n) return getkth(l, n, s, m, k); if (m == 0) return l[k - 1]; if (k == 1) return min(s[0], l[0]); int i = min(m, k / 2), j = min(n, k / 2); if (s[i - 1] > l[j - 1]) return getkth(s, m, l + j, n - j, k - j); else return getkth(s + i, m - i, l, n, k - i); return 0; } double findMedianSortedArrays(int A[], int m, int B[], int n) { int l = (m + n + 1) >> 1; int r = (m + n + 2) >> 1; return (getkth(A, m ,B, n, l) + getkth(A, m, B, n, r)) / 2.0; }};
- LeetCode OJ4 Median of Two Sorted Arrays 小结
- LeetCode: Median of Two Sorted Arrays
- LeetCode Median of Two Sorted Arrays
- leetcode 26: Median of Two Sorted Arrays
- Leetcode 4 Median of Two Sorted Arrays
- [Leetcode] Median of Two Sorted Arrays
- LeetCode 4 - Median of Two Sorted Arrays
- [LeetCode]Median of Two Sorted Arrays
- leetcode Median of Two Sorted Arrays
- LeetCode-Median of Two Sorted Arrays
- [LeetCode] Median of Two Sorted Arrays
- [LeetCode] Median of Two Sorted Arrays
- [leetcode] Median of Two Sorted Arrays
- leetcode-004:Median of Two Sorted Arrays
- Leetcode 4 Median of Two Sorted Arrays
- leetcode之 median of two sorted arrays
- 【转载】【leetcode】Median of Two Sorted Arrays
- LeetCode - Median of Two Sorted Arrays
- 小白书隐式图搜索之八数码问题
- 递归
- Unity物理引擎:Charactor Controller简介
- classpath & classpath*
- 10026 - Shoemaker's Problem(贪心)
- LeetCode OJ4 Median of Two Sorted Arrays 小结
- Eclipse启动Weblogic控制台显示乱码解决办法
- 最长公共子序列
- NSDate的一个分类,判断是否是今天,昨天,今年,获得与当前时间的差距,返回一个只有年月日的日期
- hdu4099(trie树,斐波那契数列)
- B\S备忘录28——EF强行多租户效果?谁来进谁的库
- C++中不能被声明为虚函数的函数
- Objective-C 学习笔记 12 预处理程序
- OC-字符串集合补充