leetcode笔记-4.两个排序数组的中位数

0.问题描述

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。

请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。

你可以假设 nums1 和 nums2 不同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

中位数是 (2 + 3)/2 = 2.5

1.问题分析

难度为difficult的题出人意料的AC了!

题目是给了两个已知顺序的数组,这点很关键。要求中位数。vector好的一点是内部提供了求长度的函数,如果没有的话其实我们的算法里也可以添加。那么就同时遍历两个数组,将两者比较的较小数压到新的数组中去。最后根据新数组的长度奇偶性分类,奇数就直接取1/2的位置,偶数在进行取平均数运算。

当然了,事后冷静一下眉头一皱发现不简单。这道题的本意似乎不是使用这么暴力的解法,应当是使用折半查找的策略进行计算。

2.C++代码

class Solution {
public:
	double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
		vector<int> nums;
		int i = 0, j = 0;
		while (i <= nums1.size() && j <= nums2.size()) {
			if (nums1[i] < nums2[j]) {
				nums.push_back(nums1[i]);
				i++;
				continue;
			}
			else {
				nums.push_back(nums2[j]);
				j++;
				continue;
			}
		}
		if (i < nums1.size()) {
			for (; i < nums1.size(); i++) {
				nums.push_back(nums1[i]);
			}
		}
		if (j < nums2.size()) {
			for (; j < nums2.size(); j++) {
				nums.push_back(nums2[j]);
			}
		}
		double res;
		int len = nums.size();
		if (len % 2) {
			res = nums[len / 2 + 1];
		}
		else {
			res = (nums[len / 2] + nums[len / 2 + 1]) / 2;
		}
		return res;
	}

};

要注意的是,最后取中位数位置时,直接除以2就是中位数的位置,不用加1,因为数组是从0开始计算的。

并且这个方法的复杂度是O(m+n)emmm

3.C++折半查找

最好的方法是这个,时间的复杂度为O(log(m+n))。采用折半查找的方法。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m, n;
        double result;
        vector<int> A,B;
        if (nums1.size() <= nums2.size()) {
            A = nums1;
            B = nums2;
            m = nums1.size();
            n = nums2.size();
        }
        else {
            A = nums2;
            B = nums1;
            m = nums2.size();
            n = nums1.size();
        }
        if (m == 0) {
            if (n % 2) {
                return B[n/2];
            }
            else {
                return (B[n/2-1] + B[n/2])/2.0;
            }
        }
        int i = 0;
        int j = (m + n + 1)/2 - i;
        if (B[j-1] <= A[i] && j != n) {
            if ((m + n) % 2) {
                result = B[j-1];
                return result;
            }
            else {
                result = A[i] < B[j] ? (A[i] + B[j-1])/2.0 : (B[j] + B[j-1])/2.0;
                return result;
            }
        }
        else if (B[j-1] <= A[i]) {
            if ((m + n) % 2) {
                result = B[j-1];
                return result;
            }
            else {
                result = (A[i] + B[j-1])/2.0;
                return result;
            }
        }
        i = m; 
        j = (m + n + 1)/2 - i;
        if (A[i-1] <= B[j] && j != 0) {
            if ((m + n) % 2) {
                result = A[i-1] > B[j-1] ? A[i-1] : B[j-1];
                return result;
            }
            else {
                result = A[i-1] > B[j-1] ? (A[i-1] + B[j])/2.0 : (B[j-1] + B[j])/2.0;
                return result;
            }
        }
        else if (A[i-1] <= B[j]) {
            if ((m + n) % 2) {
                result = A[i-1];
                return result;
            }
            else {
                result = (A[i-1] + B[j])/2.0;
                return result;
            }
        }
        //折半查找
        int sta = 1,end = m - 1;
        while (sta <= end) {
            i = (sta + end)/2;
            j = (m + n + 1)/2 - i;
            if (A[i -1] > B[j]) {
                end = i - 1;
            }
            else if (B[j-1] > A[i]) {
                sta = i + 1;
            }
            else {
                break;
            }
        }
        if ((m + n) % 2) {
            result = A[i-1] > B[j-1] ? A[i-1] : B[j-1];
            return result;
        }
        else {
            int fmax = A[i-1] > B[j-1] ? A[i-1] : B[j-1];
            int lmin = A[i] < B[j] ? A[i] : B[j];
            result = (fmax + lmin)/2.0;
            return result;
        }
    }
};

4.Java解法

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n1 = nums1.length;
        int n2 = nums2.length;
        if (n1>n2)
            return findMedianSortedArrays(nums2, nums1);
        int k = (n1 + n2 + 1)/2;
        int left = 0;
        int right = n1;
        while(left < right){
            int m1 = left +(right - left)/2;
            int m2 = k - m1;
            if (nums1[m1] < nums2[m2-1])
                left = m1 + 1;
            else
                right = m1;
        }
        int m1 = left;
        int m2 = k - left;
        int c1 = Math.max(m1 <= 0 ? Integer.MIN_VALUE : nums1[m1-1],
                         m2 <= 0 ? Integer.MIN_VALUE : nums2[m2-1]);
        if ((n1 + n2) % 2 == 1)
            return c1;
        int c2 = Math.min( m1 >= n1 ? Integer.MAX_VALUE :nums1[m1],
                         m2 >= n2 ? Integer.MAX_VALUE : nums2[m2]);
        return (c1 + c2) * 0.5;
        
    }
}

5.Python解法

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        l1=len(nums1)
        l2=len(nums2)
        l=l1+l2
        if l==0:
            return None
        if l==1:
            if nums1:
                return nums1[-1]
            if nums2:
                return nums2[-1]
        
        num=[]
        i=j=0
        while i<len(nums1) and j<len(nums2):
            if nums1[i]>nums2[j]:
                num.append(nums2[j])
                j+=1
            elif nums1[i]<nums2[j]:
                num.append(nums1[i])
                i+=1
            else:
                num.append(nums1[i])
                num.append(nums2[j])
                i+=1
                j+=1
                
        while i<len(nums1):
            num.append(nums1[i])
            i+=1
            
        while j<len(nums2):
            num.append(nums2[j])
            j+=1   
            
        if l%2==0:
            return float((num[l//2-1]+num[l//2])/2)
        else:
            return float(num[l//2])
        

使用折半查找的Python算法:

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        n1 = len(nums1)
        n2 = len(nums2)
        if n1 > n2:
            return self.findMedianSortedArrays(nums2,nums1)
        k = (n1 + n2 + 1)//2
        left = 0
        right = n1
        while left < right :
            m1 = left +(right - left)//2
            m2 = k - m1
            if nums1[m1] < nums2[m2-1]:
                left = m1 + 1
            else:
                right = m1
        m1 = left
        m2 = k - m1 
        c1 = max(nums1[m1-1] if m1 > 0 else float("-inf"), nums2[m2-1] if m2 > 0 else float("-inf") )
        if (n1 + n2) % 2 == 1:
            return c1
        c2 = min(nums1[m1] if m1 < n1 else float("inf"), nums2[m2] if m2 <n2 else float("inf"))
        return (c1 + c2) / 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值