一、解题思路
核心思路就是先把两个数组分割成相等的左右两个部分;无法等分时,允许一侧多一个或者少一个。然后相向移动分割点,直到满足left1 <= righ2 && left2 <= right1
二、代码
/**
* @brief 获取数组两个中间元素的索引
* @param arraySize 数组长度
* @param left 靠左的中间元素的索引
* @param right 靠右的中间元素的索引
* @param leftSide 元素总数为奇数时,是否向左侧取中间元素
* @return 左侧元素个数减去右侧元素个数
*/
int GetTwoMedianIndex(size_t arraySize, int64_t &left, int64_t &right, bool leftSide)
{
if (arraySize % 2 == 0) {
// 元素个数为偶数
right = static_cast<int64_t>(arraySize / 2);
left = right - 1;
return 0;
} else if (leftSide) {
// 元素个数为奇数,且向左侧取中间元素
right = static_cast<int64_t>(arraySize / 2);
left = right - 1;
return -1;
} else {
// 元素个数为奇数,且向右侧取中间元素
left = static_cast<int64_t>(arraySize / 2);
right = left + 1;
return 1;
}
}
//! 查找两个有序数组的中位数
double FindMedianOfSortedArrays(const std::vector<int> &nums1, const std::vector<int> &nums2)
{
int leftMinusRight(0); // 左侧元素的数量-右侧元素的数量
int64_t left1, right1;
leftMinusRight += GetTwoMedianIndex(nums1.size(), left1, right1, true);
int64_t left2, right2;
leftMinusRight += GetTwoMedianIndex(nums2.size(), left2, right2, false);
while (true) {
if (left1 >= 0 && left1 < nums1.size() && right2 >= 0 && right2 < nums2.size() &&
nums1[left1] > nums2[right2]) {
--left1;
--right1;
++left2;
++right2;
continue;
}
if (left2 >= 0 && left2 < nums2.size() && right1 >= 0 && right1 < nums1.size() &&
nums2[left2] > nums1[right1]) {
++left1;
++right1;
--left2;
--right2;
continue;
}
break;
}
std::set<int> leftResults;
std::set<int> rightResults;
if (left1 >= 0 && left1 < nums1.size()) {
leftResults.emplace(nums1[left1]);
}
if (right1 >= 0 && right1 < nums1.size()) {
rightResults.emplace(nums1[right1]);
}
if (left2 >= 0 && left2 < nums2.size()) {
leftResults.emplace(nums2[left2]);
}
if (right2 >= 0 && right2 < nums2.size()) {
rightResults.emplace(nums2[right2]);
}
if (leftMinusRight == -1) {
return *rightResults.begin();
} else if (leftMinusRight == 1) {
return *leftResults.rbegin();
} else {
return *rightResults.begin() * 0.5 + *leftResults.rbegin() * 0.5;
}
}