当前位置:首页 > 牛客 > 牛客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项的值。面对此类递...

力扣第44题:寻找两个正序数组的中位数 - 合并排序解法详解

力扣第44题:寻找两个正序数组的中位数 - 合并排序解法详解

内容简介本文详细解析了力扣第44题"寻找两个正序数组的中位数"的合并排序解法。通过双指针技术合并两个有序数组,然后直接计算合并后数组的中位数。虽然时间复杂度为O(m+n),但这种方...

牛客14496题解:括号最大深度问题(栈思想与代码优化)

牛客14496题解:括号最大深度问题(栈思想与代码优化)

一、题目解读牛客14496题要求计算给定括号字符串中的最大深度。例如,对于字符串 "(()())",最大深度为2。题目考察对括号嵌套结构的理解,以及如何通过编程找到最深嵌套层次。二...

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

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

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

牛客23458题解析:基于二分查找的动态规划解法与代码实现

牛客23458题解析:基于二分查找的动态规划解法与代码实现

一、题目解读牛客23458题要求将给定的整数数组划分为m个连续子数组,使得每个子数组的和不超过某个最大值,且该最大值尽可能小。题目本质是求解“最小化最大值”的优化问题,需要结合二分查找与动态规划思想,...

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

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

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

发表评论

访客

看不清,换一张

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