Administrator
Administrator
Published on 2024-11-21 / 8 Visits
0
0

寻找两个正序数组的中位数O(log(m+n))

寻找两个正序数组的中位数O(log(m+n))

参考文章:寻找两个有序数组的中位数(leetcode官方题解)

题目

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

 

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
 

 

提示:

nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106

题解

定义:若两个数组合并后共奇数个,则令(m+n+1)/2​个数字归类到数组左边,若共偶数个,则令(m+n)/2​个数字归类到左边

image

则据此,我们可以得出合并后数组左边的数字数量,我们在两个分数组里各自寻找一条划分线,使划分线左边的数字数量和等于我们的定义值,那么,当满足nums1[left1]<=nums2[left2+1]&&nums2[left2]<=nums1[left1+1]​时,这条分界线就是我们在合数组中的分界线,此时

return nums1.size()+nums2.size())%2==1?max(nums1[left1],nums2[left2]):
	static_cast<double>(max(nums1[left1],nums2[left2])+min(nums1[left1+1],nums2[left2+1]))/2.0;

即是我们所求的合数组的中位数。

除此以外,还要考虑许多额外可能性并进行针对性处理,比如:

  • 数组中包含负数
  • 存在空数组
  • 某一个数组的所有数字小于或大于另一个数组的所有数字
  • 只有1个数字的数组

详细代码如下:

/*
 * @lc app=leetcode.cn id=4 lang=cpp
 *
 * [4] 寻找两个正序数组的中位数
 */

// @lc code=start
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int totalLeft = (nums1.size() + nums2.size() + 1)/2-2;
        int left1 = (nums1.size()-1)/2;
        while (1) {
            int left2 = totalLeft - left1;
            if(left2 != nums2.size()-1&&left1 != -1&&nums1[left1]>nums2[left2+1]){
                --left1;
                continue;
            }
            else if(left1 != nums1.size()-1&&left2 != -1&&nums2[left2]>nums1[left1+1]){
                ++left1;
                continue;
            }
            else{
                int n1l1,n2l2,n1l1plus,n2l2plus;
                if(left1 == -1){
                    n1l1 = INT_MIN;
                }
                else{
                    n1l1 = nums1[left1];
                }
                if(left1 == nums1.size()-1){
                    n1l1plus = INT_MAX;
                }
                else{
                    n1l1plus = nums1[left1+1];
                }
                if(left2 == -1){
                    n2l2 = INT_MIN;
                }
                else{
                    n2l2 = nums2[left2];
                }
                if(left2 == nums2.size()-1){
                    n2l2plus = INT_MAX;
                }
                else{
                    n2l2plus = nums2[left2+1];
                }
                return (nums1.size()+nums2.size())%2==1?max(n1l1,n2l2):static_cast<double>(max(n1l1,n2l2)+min(n1l1plus,n2l2plus))/2.0;
            }
        }
      
    }
};
// @lc code=end



Comment