HR面完刚好是周末,没有办法只能焦急的等待腾讯的offer…,为了缓解情绪,继续做做LeetCode还有学学unity。
题目描述
思路 二分法
跟我们常见的二分法有挺大的区别,但是本质还是不断舍弃一半的数。
困难题都是思路说破就没啥了,但是自己想基本想不出来。
本题思路:
我们把寻找中位数的过程当成寻找第k个数的过程,如果两个数组总长为奇数,只需寻找第k/2 +1个数,如果两个数组总长为偶数,寻找第k/2个数和第k/2 + 1个数。
接下来就是不曾见过的船新二分法了!!
我们设所寻找的数为第n个,设置两个指针index1和index2,一个起始为数组一的0号元素,一个起始为数组二的0号元素。
然后我们每次取包括指针所指元素在内的第n/2个元素,比较两个数组该元素的大小
关键来了,小的那一方的这n/2个元素不可能是第n大的元素。因为第n/2最好情况下都会小于大的那一方的第n/2个,所以它最大也就是第n - 1个,所以我们可以把这n/2个元素排除。
然后被排除的数字就没有意义了,我们就将指针移动到下一个位置,同时n减去排除了几个数字。这里要注意,n/2处可能会大于数组长度,这时候就比较数组最后一个数,最后n也是减去到最后一个元素为止有几个数。
具体例子:windliang
class Solution {
//思路:
//每次取两个数组的第k/2个数比较,小的那一方的前k/2个数不可能是第k个,舍弃,以此类推直到找到第k个
//求两次,使偶数的时候能找到k/2和k/2+1,奇数的时候能找到两个k/2
public:
int getK(vector<int> nums1, vector<int> nums2, int k) {
int len1 = nums1.size();
int len2 = nums2.size();
int index1 = 0, index2 = 0;
while(1) {
//数组1的元素已经被全部排除,剩下的第k大个个数只能在index2后面的第k个
//为什么需要-1,因为index本身已经包括一个数字
//因为index是下一个数,所以会等于数组长度。
if(index1 == len1) {
return nums2[index2 + k - 1];
}
if(index2 == len2) {
return nums1[index1 + k - 1];
}
if(k == 1) {
return min(nums1[index1], nums2[index2]);
}
int newIndex1 = min(index1 + k / 2 - 1, len1 - 1);
int newIndex2 = min(index2 + k / 2 - 1, len2 - 1);
if(nums1[newIndex1] <= nums2[newIndex2]) {
//newIndex1到index1之间有几个数字
k -= newIndex1 - index1 + 1;
//下一个index从newIndex1的下一个数开始
index1 = newIndex1 + 1;
} else {
k -= newIndex2 - index2 + 1;
index2 = newIndex2 + 1;
}
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int wholeLen = nums1.size() + nums2.size();
if(wholeLen % 2 == 0) {
return (getK(nums1, nums2, wholeLen / 2) + getK(nums1, nums2, wholeLen / 2 + 1) )/ 2.0;
} else {
return getK(nums1, nums2, wholeLen / 2 + 1);
}
}
};
时间复杂度O(log(m+n))
空间复杂的O(1)