Leetcode-Median of Two Sorted Arrays
来源:互联网 发布:淘宝链接地址怎么弄 编辑:程序博客网 时间:2024/06/05 16:00
- 前言
- 题目分析1
- 算法的正确性
- 代码
- 效率
- 题目分析2
- 算法的正确性
- 代码
- 效率
- 推广
- 结语
前言
Leetcode刷到150道了,各种题型都已经练习了一遍,没有必要再去刷数量了!分类总结解题方法,完善知识体系已经是刻不容缓了。尤其是在看了《暗时间》之后,深有感触。总结、反思自己的思维过程也许是最重要的。对每道题进行深加工,抽象出一般的概念,得到一般的解题策略。这个过程才是最重要的,是沉淀思想的绝好途径。
先简单摘一些常用的解题方法,以后每碰到难题的时候,都要想一下用这些方法是否可以解决:
时刻不忘未知量
时刻要想到自己的问题是什么,要求什么。用特例启发思考
构造一个合适的实例,可能会发现一般的规律。反过来推导
设立未知数,从结论出发,向已知条件靠扰。试错
- 调整题目的条件
去掉一个条件,观察区别,再放上那个条件,感觉到题目的内在结构上的某种约束,进而得到答案。 - 求解一个类似的题目
为了优化脑中的知识结构,我们在记忆掌握和分析问题的时候都应该尽量抽象地去看待,这样才能建立知识的本质联系。 - 列出所有可能与题目有关的定理或性质
比如这道题目,可以列出这样的性质:中位数是数组中最中间的数。如果元素总数为奇数,它左边所有元素的个数和右边所有元素的个数相等;如果为偶数,则将所有元素平分成两左右两部分,两部分元素个数相等, 中位数为最中间两者的均值。 - 考察反面,考察其他所有情况
- 将问题泛化
这道题应该要进行泛化,比如如果要求两个排序元素里的第K大元素怎么求?如果是n个排序数组呢?
题目分析1
Leetcode-CPP_p14
可以从结论来推导方法:题目要求用
假设
可以得到:
对于情形
这里我们不能排除
因为我们是要寻找第永远不要忘了我们的目的是什么——走得太远,不要忘了当初是为什么出发!
而我们已经排除了
情形
而情形
虽然我们不知道
算法的正确性
如何证明算法的正确性呢?
每次递归都会排除一半的元素或者排除掉整个数组,即当
代码
int getKth(int a[], int m, int b[], int n, int k){ if (m > n) return getKth(b, n, a, m, k); if (0 == m) return b[k-1]; if (1 == k) return min(a[0], b[0]); int i = min((k+1)/2, m); /*if (a[i-1] < b[i-1]) return getKth(a+i, m-i, b, n, k-i); else if (a[i-1] > b[i-1]) return getKth(a, m, b+i, n-i, k-i);*/ int j = k-i; if (a[i-1] < b[j-1]) return getKth(a+i, m-i, b, n, k-i); else if (a[i-1] > b[j-1]) return getKth(a, m, b+i, n-i, k-j); else return a[i-1];}double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){ int total = nums1Size+nums2Size; if (total & 1) //odd return getKth(nums1, nums1Size, nums2, nums2Size, total/2+1); else //even return (getKth(nums1, nums1Size, nums2, nums2Size, total/2+1) + getKth(nums1, nums1Size, nums2, nums2Size, total/2))/2.0; }
代码中注释的地方是有问题的,如果只是比较
A[i−1] 和B[i−1] ,那么无论i 是等于k2 还是等于k+12 ,最后都是不能直接用后面三种情况来处理的。所以我们还需要一个变量j=k−i 来保证目前我们比较的元素个数为k 。还是那句话,不要忘了最初的目的是什么。所以这里的关键在于选出
k 个数,比较每个一维数组的最后一个元素的大小。对于kn 大于一维数组的长度m 的情形,就会越界,这时只能取m 个元素了,那另外一个数组就必须取k−m 个元素了,对于n==2 时,显然k−m 对于第2个数组是不越界的。但对n>2 的情形,则情况会复杂很多。
下面是用vector加上迭代器的代码:
int getKthOfVectors(vector<int>& nums1, vector<int>::iterator it1, vector<int>& nums2, vector<int>::iterator it2, int k){ int sz1 = nums1.end()-it1; int sz2 = nums2.end()-it2; if (sz1 > sz2) return getKthOfVectors(nums2, it2, nums1, it1, k); if (0 == sz1) return *(it2+k-1); if (1 == k) return min(*it1, *it2); int i = min((k+1)/2, sz1); int j = k-i; if (*(it1+i-1) < *(it2+j-1)) { it1 += i; return getKthOfVectors(nums1, it1, nums2, it2, k-i); } else if (*(it1+i-1) > *(it2+j-1)) { it2 += j; return getKthOfVectors(nums1, it1, nums2, it2, k-j); } else return *(it1+i-1);}double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2){ int total = nums1.size()+nums2.size(); if (total & 1) //odd return getKthOfVectors(nums1, nums1.begin(), nums2, nums2.begin(), (total+1)/2); else //even return (getKthOfVectors(nums1, nums1.begin(), nums2, nums2.begin(), total/2+1)+getKthOfVectors(nums1, nums1.begin(), nums2, nums2.begin(), total/2))/2.0;}
效率
假定
题目分析2
根据discuss里分享的解答,还可以利用中位数的这一性质:中位数两边的元素个数相等(或相差1)
。列出这一性质并不难,难就难在怎么根据这一性质继续往下走。
当左右两部分的元素个数相等或者相差1时,而且
由此,可列方程
因此我们只要在
算法的正确性
每次查找,要么找到
代码
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2){ int sz1 = nums1.size(); int sz2 = nums2.size(); if (sz1 > sz2) return findMedianSortedArrays(nums2, nums1); int imin = 0; int imax = sz1; int i, j; while (imin <= imax) { i = (imin+imax)/2; j = (sz1+sz2+1)/2 - i; if (i > 0 && j < sz2 && nums2[j] < nums1[i-1]) imax = i-1; else if (j > 0 && i < sz1 && nums1[i] < nums2[j-1]) imin = i+1; else break; } int num1; if (0 == i) num1 = nums2[j-1]; else if (0 == j) num1 = nums1[i-1]; else num1 = max(nums1[i-1], nums2[j-1]); if ((sz1+sz2) & 1) //odd return num1; int num2 = min(nums1[i], nums2[j]); return (num1+num2)/2.0;}
注意:代码最后返回时用到除法,除数要用2.0,否则返回的是int类型转换到double,结果错误。
效率
二分查找的效率当然是
推广
如果是在
根据思路1,我们可以比较每个数组的第
上面所说的是理想情况下,实际写代码的时候要考虑的东西稍复杂一些,当数组的元素个数小于
因此,可以推广为找出二维vector中的第
接口为:
double findMedianSortedArrays(vector<vector<int>> &nums, int k)
效率又该怎么计算呢?
这里主定理
对应,我们用
复杂度与
n 其实没有关系,只与b 有关,因此T(n)=O(1) 。
每次递归后
n 都会变成原来的1b ⇒ T(n)=T(n/b)+O(1) ,由主定理⇒ T(n)=logn 。
最坏情况下,每次只能排除一个数,那么时间复杂度就会降为O(n)
结语
如果
不管怎么说,第一篇博客,加油!!!
- 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
- [LeetCode]Median of Two Sorted Arrays
- [超源点:还是最短路的变形]hdu2066
- import opencv for Android 例程总是显示错去
- 用sql来判断子集
- Matlab优化函数中options选项的修改
- javascript 对象
- Leetcode-Median of Two Sorted Arrays
- Adaboost-积分图计算
- java中hashcode()和equals()的的用法整理
- json的使用
- 前端开发资源汇总
- 使用netbeans实现一个简易计算器
- CATransition 的初级应用及type属性
- 面试题_Java中各种(类、方法、属性)访问修饰符与修饰符的说明
- bat脚本自动扫描制定文件夹下shp文件,并导入数据库,然后执行空间操作