Median of Two Sorted Arrays---LeetCode进阶路④

  • 题目描述

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

You may assume nums1 and nums2 cannot be both empty.

分别有大小为m和n的有序数组nums1和nums2。

求两个排序数组的中值。总的运行时复杂度应该是O(log (m+n))。

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

Example 1:

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

The median is 2.0

Example 2:

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

The median is (2 + 3)/2 = 2.5
  • 思路分析:

需求是输出两个有序数组的中值,想要实现很是简单,最直接粗暴的方法是把两个数组合并,找到相应元素,时间复杂度为O(m+n)。但题目明确要求时间复杂度需要控制在O(log(m+n)),就必须思考优化版方法啦。

小陌目前的优化方法是用寻找第k小数(因为给出的两个数组皆有序,则k对应(m+n)/2):

每次比较两个数组的第k/2个大的数:

  1. nums1[k/2] = nums[k/2],那么这个数就是我们要找的第K小数
  2. nums1[k/2] > nums[k/2],则说明第K小数不在nums2中前k/2个元素,可排除
  3. nums1[k/2] < nums[k/2],与2同理,排除nums1中前k/2个元素

    如此操作,每次都能排除k/2的元素(递归过程中,可能会出现数组个数不到k/2的情况,并不会影响算法,从另一个数组进行补充,多取相应元素即可)。 

当k=1时,找到第K小数,结束递归

  • 原码附录:
  1. 简单粗暴法
    class Solution {
        public double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int all = nums1.length+nums2.length;
            int[] result = new int[all];
            for(int i=0;i<all;i++){
                result[i] = (i<nums1.length)?nums1[i]:nums2[i-nums1.length];
            }
            Arrays.sort(result);
            return (all%2) ==1 ? result[(all-1)/2]:(double)(result[all/2]+result[all/2-1])/2;
        }
    }
  2. top k算法思想

 

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
       if((nums1.length+nums2.length)%2==0){
           return (findK(nums1,0,nums1.length-1,nums2,0,nums2.length-1,(nums1.length+nums2.length)/2)
                   +findK(nums1,0,nums1.length-1,nums2,0,nums2.length-1,(nums1.length+nums2.length)/2+1))/2.0;
       }
       else{
            return findK(nums1,0,nums1.length-1,nums2,0,nums2.length-1,(nums1.length+nums2.length)/2+1);
       }
    }
    
    public int findK(int[] nums1,int n1,int n2,int[] nums2,int m1,int m2,int k){
        int i = n2 - n1 +1;
        int j = m2 - m1 +1;
        
        if(i>j){
            return findK(nums2,m1,m2,nums1,n1,n2,k);
        }
        if(i == 0){
            return nums2[m1+k-1];
        }
        if(k == 1){
            return Math.min(nums1[n1],nums2[m1]);
        }
            
        int mid1 = Math.min(k/2,i);
        int mid2 = k - mid1;
        if(nums1[n1+mid1-1]==nums2[m1+mid2-1]){
            return nums1[n1+mid1-1];
        }
        else if(nums1[n1+mid1-1]>nums2[m1+mid2-1]){
            return findK(nums1,n1,n1+mid1-1,nums2,m1+mid2,m2,k-mid2);
        }
        else{
            return findK(nums1,n1+mid1,n2,nums2,m1,m2+mid2-1,k-mid1);
        }
    }
}

以下内容为可耻的自我推销,完全可忽略(。•́ωก̀。).。

此处厚脸皮的安利小透明公众号 林夏夏

夏夏大大的英雄梦,
就是能和最喜欢的你,
分享一道算法题,
温习一个编程上易忽视小细节,
品一份书香氤氲,
道最后一句晚安ヾ(◍°∇°◍)ノ゙

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值