当前位置:首页 > 牛客 > 牛客231765题解析:高效求解两个有序数组中位数的分治算法(附代码详解)

牛客231765题解析:高效求解两个有序数组中位数的分治算法(附代码详解)

4个月前 (08-22)

牛客231765题解析:高效求解两个有序数组中位数的分治算法(附代码详解) 分治法 二分查找 牛客题解 数组 第1张

一、题目解读

牛客231765题要求求解两个有序数组的中位数。给定两个长度分别为m和n的有序数组arr1和arr2,需找到合并后数组的中位数。中位数定义为排序后位于中间位置的元素,若总长度为奇数则直接取中间值,偶数则取中间两个元素的平均值。本题的核心在于如何在O(log(m+n))时间内高效找到这个中位数,避免直接合并排序带来的O(m+n)复杂度。

二、解题思路

采用分治法,通过二分查找分割点来减少比较次数。关键思想是:在两个数组中找到合适的分割点(即arr1的第k1位置和arr2的第k2位置),使得分割后的左右两部分元素数量总和满足中位数的定义。通过比较分割点两侧的最大值(左部分)与最小值(右部分),判断当前分割是否满足条件,进而缩小搜索范围。通过二分法,将时间复杂度控制在O(log(m+n))。

三、解题步骤详解

1. 确定基准数组:确保arr1为较短数组,若arr2更短则交换,减少后续循环次数。

2. 二分查找分割点:在arr1中通过二分法寻找分割点partition1,根据总长度计算arr2的分割点partition2。

3. 处理边界情况:当partition1或partition2为0或数组末尾时,特殊处理边界值(如INT_MIN/INT_MAX),避免越界。

4. 判断分割有效性:比较两侧的最大值(左)与最小值(右),若满足maxLeft1 ≤ minRight2 且 maxLeft2 ≤ minRight1,则找到正确分割点。

5. 递归调整:若分割不满足条件,根据大小关系调整二分范围(缩小左侧或右侧),继续循环查找。

6. 返回结果:最终合并数组的上中位数为两个分割点左侧的最大值(即max(maxLeft1, maxLeft2))。

四、代码与注释

class Solution {
public:
    int getUpMedian(vector<int>& arr1, vector<int>& arr2) {
        // 确保arr1是较短的数组
        if (arr1.size() > arr2.size()) {
            return getUpMedian(arr2, arr1); // 递归交换数组
        }
        
        int m = arr1.size();
        int n = arr2.size();
        int total = m + n;
        int low = 0, high = m; // 二分范围初始化
        
        while (low <= high) {
            int partition1 = (low + high) / 2; // 当前分割点
            int partition2 = (total + 1) / 2 - partition1; // 对应arr2的分割点
            
            // 处理边界情况
            int maxLeft1 = (partition1 == 0)? INT_MIN : arr1[partition1 - 1];
            int minRight1 = (partition1 == m)? INT_MAX : arr1[partition1];
            
            int maxLeft2 = (partition2 == 0)? INT_MIN : arr2[partition2 - 1];
            int minRight2 = (partition2 == n)? INT_MAX : arr2[partition2];
            
            // 找到正确的分割点
            if (maxLeft1 <= minRight2 && maxLeft2 <= minRight1) {
                // 返回上中位数(合并数组中间位置的较大值)
                return max(maxLeft1, maxLeft2);
            } 
            else if (maxLeft1 > minRight2) {
                // 分割点需要左移(缩小右侧范围)
                high = partition1 - 1;
            } 
            else {
                // 分割点需要右移(扩大右侧范围)
                low = partition1 + 1;
            }
        }
        
        return -1; // 理论上不会执行到这里
    }
};

注释解析:通过递归交换数组长度确保arr1较短,利用二分法动态调整分割点,结合边界处理避免数组越界,最终通过比较分割点两侧的极值确定中位数位置。

五、总结

本解法巧妙利用分治与二分查找,将复杂的中位数问题转化为分割点的有效性验证。通过边界条件的严谨处理,避免了合并排序的高耗时,实现了O(log(m+n))时间复杂度。该算法适用于大规模有序数组场景,是解决中位数问题的经典优化方案。理解此算法有助于提升对分治思想和二分优化的应用能力。

原创内容 转载请注明出处

分享给朋友:

相关文章

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

一:重新解读题目泰波那契数列是一个充满数学趣味的递推序列:从第3项开始,每个数均为前三个数的和(即Tₙ₊₃ = Tₙ + Tₙ₊₁ + Tₙ₊₂)。当给定整数n时,需要高效计算出第n项的值。面对此类递...

牛客NC67题解:汉诺塔递归算法与解题步骤

牛客NC67题解:汉诺塔递归算法与解题步骤

一、题目解读牛客NC67题要求解决汉诺塔问题,这是一个经典的递归算法题目。题目给定整数n,代表汉诺塔中的盘子数量,需要输出将n个盘子从起始柱移动到目标柱的所有步骤。汉诺塔问题规则为:每次只能移动一个盘...

牛客232639题解析:双指针+排序算法高效求解三角形数量(附代码详解)

牛客232639题解析:双指针+排序算法高效求解三角形数量(附代码详解)

一、题目解读牛客232639题要求计算一个整数数组中能够组成有效三角形的三边组合数量。根据三角形不等式,三边需满足任意两边之和大于第三边。例如,数组[3, 4, 5, 6]可组成两个有效三角形([3,...

牛客4432题解题全解析:矩阵快速幂优化楼梯攀登问题(附C++代码)

牛客4432题解题全解析:矩阵快速幂优化楼梯攀登问题(附C++代码)

一、题目解读牛客4432题要求计算在n阶楼梯中,每次可爬1阶或2阶,共有多少种不同的攀登方式。该问题属于经典的动态规划类题目,需通过数学递推或矩阵乘法优化算法以应对较大数据规模。题目核心在于寻找高效计...

牛客4577题解:滑动窗口解法

牛客4577题解:滑动窗口解法

一、题目解读牛客4577题要求处理多组测试数据,每组包含一个整数数组crimes和两个参数n(数组长度)、t(阈值)、c(窗口大小)。题目需要统计数组中所有长度恰好为c的子数组,其元素和不超过t的数量...

牛客13278题详解:句子单词反转(C++实现)

牛客13278题详解:句子单词反转(C++实现)

一、题目解读牛客13278题要求编写函数实现句子中单词顺序的反转,例如将"Hello World"转换为"World Hello"。需注意处理首尾空格、单词间空...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。