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

2021/3/5

# Heading

    4.寻找两个正序数组的中位数 (opens new window)

    Tags: algorithms adobe apple dropbox google microsoft yahoo zenefits array binary-search divide-and-conquer

    Langs: c cpp csharp golang java javascript kotlin php python python3 racket ruby rust scala swift typescript

    • algorithms
    • Hard (39.49%)
    • Likes: 3767
    • Dislikes: -
    • Total Accepted: 346.3K
    • Total Submissions: 872.8K
    • Testcase Example: '[1,3]\n[2]'

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

    示例 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
    

    示例 3:

    输入:nums1 = [0,0], nums2 = [0,0]
    输出:0.00000
    

    示例 4:

    输入:nums1 = [], nums2 = [1]
    输出:1.00000
    

    示例 5:

    输入:nums1 = [2], nums2 = []
    输出:2.00000
    

    提示:

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

    进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?

    /*
     * @lc app=leetcode.cn id=4 lang=javascript
     *
     * [4] 寻找两个正序数组的中位数
     */
    
    // @lc code=start
    /**
     * @param {number[]} nums1
     * @param {number[]} nums2
     * @return {number}
     */
    var findMedianSortedArrays = function (nums1, nums2) {
        let i = 0, j = 0;
        const ret = [];
        while (i < nums1.length || j < nums2.length) {
            if (i < nums1.length && j < nums2.length) {
                if (nums1[i] <= nums2[j]) {
                    ret.push(nums1[i++])
                } else {
                    ret.push(nums2[j++])
                }
            } else if (i < nums1.length) {
                ret.push(nums1[i++])
            } else {
                ret.push(nums2[j++])
            }
        }
        if (ret.length % 2 === 0) {
            return (ret[ret.length / 2] + ret[ret.length / 2 - 1]) / 2
        } else {
            return ret[(ret.length - 1) / 2]
        }
    };
    // @lc code=end
    
    
    // @after-stub-for-debug-begin
    module.exports = findMedianSortedArrays;
    // @after-stub-for-debug-end
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    /*
     * @lc app=leetcode.cn id=4 lang=javascript
     *
     * [4] 寻找两个正序数组的中位数
     */
    
    // @lc code=start
    /**
     * @param {number[]} nums1
     * @param {number[]} nums2
     * @return {number}
     */
    var findMedianSortedArrays = function(nums1, nums2) {
        // 较小数组用nums1表示
        if (nums1.length > nums2.length) {
            const temp = nums1
            nums1 = nums2
            nums2 = temp
        }
    
        const m = nums1.length
        const n = nums2.length
    
        // 分割线左边的所有元素需要满足的个数为 (m + n + 1) / 2
        const totalLeft = Math.floor((m + n + 1) / 2)
    
        let left = 0
        let right = m
    
        // 对较短数组nums1进行二分查找,找个一组i j 使得 Max(LeftPart) <= Min(RightPart)
        // nums1[i-1] <= nums2[j] && nums2[j-1] <= nums1[i]
        while (left < right) {
            const i = Math.floor((left + right + 1) / 2)
            const j = totalLeft - i
            if (nums1[i - 1] > nums2[j]) {
                right = i - 1
            } else {
                left = i
            }
        }
    
        const i = left
        const j = totalLeft - i
    
        const nums1LeftPartMax = i === 0 ? Number.MIN_SAFE_INTEGER : nums1[i - 1]
        const nums1RightPartMin = i === m ? Number.MAX_SAFE_INTEGER : nums1[i]
        const nums2LeftPartMax = j === 0 ? Number.MIN_SAFE_INTEGER : nums2[j - 1]
        const nums2RightPartMin = j === n ? Number.MAX_SAFE_INTEGER : nums2[j]
    
        if ((m + n) % 2 === 0) {
            return (
                (Math.max(nums1LeftPartMax, nums2LeftPartMax) +
                    Math.min(nums1RightPartMin, nums2RightPartMin)) /
                2
            )
        } else {
            return Math.max(nums1LeftPartMax, nums2LeftPartMax)
        }
    }
    // @lc code=end
    
    // @after-stub-for-debug-begin
    module.exports = findMedianSortedArrays
    // @after-stub-for-debug-end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64