Num 4 寻找两个有序数组的中位数
啊啊啊啊啊啊啊wa了无数次卡了两天我终于给这个整出来了!!!
方法很简单,各种边界条件超级无敌坑爹。
看到log就想二分。target就是中位数,或者用来取平均的两个数
target中两个数组分别占有多少部分。然后如果正常情况下,用两个里面最大的比较就行。
判断合法的是,每个数组target范围内的最后一个数比另外一个target外面的第一个数大。
需要注意的是:如果已经到了边界点,说明现有的这些都是合理的。那么这个不用比较了(因为你在上面一轮已经比较过了,确实是需要调整,才会变成现有的,所以当前是合法的)(但是两个比较条件另外一个是需要比较的)
几个要点:
1、因为需要合法/跳出特殊写的情况非常多,这里面选择先写非边界继续运行然后继续二分的状态
2、在跳出来的情况里面,存在一定可能:虽然一条不用比较,但是需要比较的另一条不符合的
3、这种情况的修改中,要考虑到往前移动可能触碰另一边边界
4、并不能直接确定是在a中还是在b中,这时候用target内最后两个比较
5、如果有范围内没有的,给个标记,让他们直接从另一个组取
6、最开始加个判定,如果整体一个数组小于另外一个数组,这时候省掉二分时间。
class Solution { public: double getNum(vector<int>&nums1,vector<int>&nums2,int target) { if(nums1.size()==0) return nums2[target-1]; if(nums1[nums1.size()-1]<=nums2[0]) { if(target<=nums1.size()) return nums1[target-1]; return nums2[target-nums1.size()-1]; } if(nums2[nums2.size()-1]<=nums1[0]) { if(target<=nums2.size()) return nums2[target-1]; return nums1[target-nums2.size()-1]; } int l=1,r=nums1.size(); int m=(l+r)/2;//mb=target-m+1;都是第几个a[m-1] b[target-m] while(l<=r) { if(m<nums1.size() && target-m<nums2.size() && nums1[m-1]>nums2[target-m]) {r=m-1;m=(l+r)/2;continue;} if(m<nums1.size() && target-m<nums2.size() && nums2[target-m-1]>nums1[m]) {l=m+1;m=(l+r)/2;continue;} break; } int leftans=m-1,rightans=target-m-1; if(target-m==nums2.size() && nums2[target-m-1]>nums1[m]) { do { leftans++; rightans--; }while(rightans>=0 && leftans<=nums1.size()-2 && nums2[rightans]>nums1[leftans+1]); } //cout<<"hh"; if(m==nums1.size() && nums1[m-1]>nums2[target-m]) { do { leftans--; rightans++; }while(leftans>=0 && rightans<=nums2.size()-2 && nums1[leftans]>nums2[rightans+1]); } //cout<<leftans<<rightans<<endl; if(leftans<0) return nums2[target-1]; if(rightans<0) return nums1[target-1]; return max(nums1[leftans],nums2[rightans]); return 1; } double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int len1=nums1.size(); int len2=nums2.size(); if(len1>len2) swap(nums1,nums2); int len=len1+len2; //getNum后面的数是排序,不是下标。 if(len%2) return getNum(nums1,nums2,len/2+1); else return (getNum(nums1,nums2,len/2)+getNum(nums1,nums2,len/2+1))*1.0/2; } };
时间才能证明一切,选好了就尽力去做吧!