寻找两个正序数组的中位数

一、解题思路

  核心思路就是先把两个数组分割成相等的左右两个部分;无法等分时,允许一侧多一个或者少一个。然后相向移动分割点,直到满足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;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值