🌈【LeetCode.正序数组的中位数】- JavaScript =>二分查找+模拟

527 阅读2分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


题意描述

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

示例 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 = [1, 2];
nums2 = [3,4];
var compare = function (x, y) {//比较函数
    if (x < y) {
        return -1;
    } else if (x > y) {
        return 1;
    }
}
var findMedianSortedArrays = function(nums1, nums2) {
    var data = nums1.concat(nums2);
    var mid; 
    data.sort(compare); 
    if (data.length%2==0){
        mid = (data[data.length/2-1]+data[data.length/2])/2
    }
    if (data.length%2!=0){
        mid = data[(data.length-1)/2]
    }
    return mid;
};
findMedianSortedArrays(nums1, nums2);

二分处理优化

将之前的按位置移动改为二分查找移动,更快的去找到分隔点。

 let findMedianSortedArrays = (nums1, nums2) => {
    
    if (nums1.length > nums2.length) { // to ensure m<=n
        [nums1,nums2] = [nums2,nums1]
    }
    let m = nums1.length;
    let n = nums2.length;
    let l = 0, r = m, halfLen = Math.floor((m + n + 1) / 2);
    console.log('halfLen',halfLen)
    while (l <= r) {
        let i = Math.ceil((r + l) / 2);
        let j = halfLen - i;
        if (i < r && nums2[j-1] > nums1[i]){
            l = l + 1; // i is too small
        }
        else if (i > l && nums1[i-1] > nums2[j]) {
            r = r - 1; // i is too big
        }
        else { // i is perfect
            let maxLeft = 0;
            if (i == 0) { maxLeft = nums2[j-1]; }
            else if (j == 0) { maxLeft = nums1[i-1]; }
            else { maxLeft = Math.max(nums1[i-1], nums2[j-1]); }
            if ( (m + n) % 2 == 1 ) { return maxLeft; }

            let minRight = 0;
            //临界值 说明nums1在m之前的数值都小于nums2
            if (i == m) { minRight = nums2[j]; }
            //临界值 说明nums2在n之前的数值都小于nums1
            else if (j == n) { minRight = nums1[i]; }
            
            else { minRight = Math.min(nums2[j], nums1[i]); }
            console.log(minRight,maxLeft)
            return (maxLeft + minRight) / 2.0;
        }
    }
        return 0.0; 
}

感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤