LeetCode 4. Median of Two Sorted Arrays

[寻找两个正序数组的中位数](https://leetcode.cn/problems/median-of-two-sorted-arrays/)

难度:HARD

思路

  1. 目标:O(log(n+m))
  2. 递归减少问题规模
  3. 在两个数组中,找出第k小数
  4. 取两数组k/2处元素比较,较小者的数组前k/2个数必然小于第k小的数,故可以删除,缩小一半问题规模,即O(log)级别

C++ 解法:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int total = nums1.size() + nums2.size();
        if (total % 2 == 0)
        {
            int left = findKthNumber(nums1, 0, nums2, 0, total / 2);
            int right = findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
            return (left + right) / 2.0;
        } 
        else 
        {
            return findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
        }
    }

    // 用于找两个数组组合序列的第k个数,i,j分别表示开始数组开始坐标
    int findKthNumber(vector<int> &nums1, int i, vector<int> &nums2, int j, int k)
    {
        if (nums1.size() - i > nums2.size() - j) return findKthNumber(nums2, j, nums1, i, k);  // 将短的放前面
        if (nums1.size() == i) return nums2[j + k - 1]; // 处理短数组删完的情况
        if (k == 1) return min(nums1[i], nums2[j]); // 处理找第一个数的情况(边界情况)
        
        // si,sj用于查找各数组k/2位置的元素
        // sj不可能越界,因为num2作为长数组至少长度也是剩余总数目的一半
        // si可能越界故要做判断,因为vector中的size函数返回值是unsigned_int
        // 而min函数接收int型参数,所以需要强转
        int si = min(i + k / 2, (int)(nums1.size())), sj = j + k / 2;
        // 删除必小于第k个元素的值
        if (nums1[si - 1] > nums2[sj - 1])
        {
            return findKthNumber(nums1, i, nums2, j + k / 2, k - k / 2);
        }
        else 
        {
            return findKthNumber(nums1, si, nums2, j, k - (si - i));
        }
    }
};

Java解法

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int total = nums1.length + nums2.length;
        if (total % 2 == 0){
            int left = getKthElement(nums1, 0, nums2, 0, total / 2);
            int right = getKthElement(nums1, 0, nums2, 0, total / 2 + 1);
            return (left + right) / 2.0;
        }else {
            return getKthElement(nums1, 0, nums2, 0, total / 2 + 1);
        }
    }

    public int getKthElement(int[] nums1, int i, int[] nums2, int j, int k) {
        if(nums1.length - i > nums2.length - j) return getKthElement(nums2, j, nums1, i, k);
        if(nums1.length == i) return nums2[j + k - 1];
        if (k == 1) return Math.min(nums1[i], nums2[j]);

        int si = Math.min(i + k / 2, nums1.length), sj = j + k / 2;
        if(nums1[si - 1] > nums2[sj - 1]){
            return getKthElement(nums1, i, nums2, sj, k - k / 2);
        }else{
            return getKthElement(nums1, si, nums2, j, k - (si - i));
        }
    }
}

Python解法

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        total = len(nums1) + len(nums2)
        if total % 2 == 0:
            left = self.find(nums1, 0, nums2, 0, total // 2)
            right = self.find(nums1, 0, nums2, 0, total // 2 + 1)
            return (left + right) / 2.0
        else:
            return self.find(nums1, 0, nums2, 0, total // 2 + 1)

    def find(self, nums1, i, nums2, j, k):
        if len(nums1) - i > len(nums2) - j:
            return self.find(nums2, j, nums1, i, k)
        if len(nums1) == i:
            return nums2[j + k - 1]
        if k == 1:
            return min(nums1[i], nums2[j])

        si = min(len(nums1), i + k // 2) # // 表示整除(向下取整)
        sj = j + k - k // 2
        if nums1[si  -1] > nums2[sj -1 ]:
            return self.find(nums1, i, nums2, sj, k - (sj - j))
        else:
            return self.find(nums1, si, nums2, j, k - (si - i))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值