打怪升级-4.寻找两个正序数组的中位数

题目描述

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

算法的时间复杂度应该为 O(log (m+n))

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

解答

方法一:
时间复杂度:O(m+n)2

package com.antg;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Antg
 * @date 2021/10/20  17:28
 */
public class Code_4 {
    public static void main(String[] args) {
        int a[] = {1,3};
        int b[] = {2};

        System.out.println(findMedianSortedArrays(a,b));

    }

    public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
        //将两个数组合
        int tem[] = new int[nums1.length+nums2.length];
        System.arraycopy(nums1,0,tem,0,nums1.length);
        System.arraycopy(nums2,0,tem,nums1.length,nums2.length);
        //排序(冒泡)
        for(int i  = 0;i<tem.length;i++){
            for(int j = 0;j<tem.length-i-1;j++){
                if(tem[j]>tem[j+1]){
                    int t = tem[j];
                    tem[j] = tem[j+1];
                    tem[j+1] = t;
                }
            }
        }
        return tem.length%2!=0?tem[(tem.length+1)/2-1]:(tem[tem.length/2-1]+tem[tem.length/2])/2.0;
    }
}

方法一的优化
中位数: 基数的话就是第(m+n+1)/2个,偶数的话就是(m+n)/2
这样的话需要分情况讨论
所以做如下优化
中位数=(m+n+1)/2和(m+n+2)/2求和之后取平均

方法二:
时间复杂度:O(log (m+n))

package com.antg;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Antg
 * @date 2021/10/20  17:28
 */
public class Code_4 {
    public static void main(String[] args) {
        int a[] = {1,3};
        int b[] = {2};

        System.out.println(findMedianSortedArrays2(a,b));
    }

    public static double findMedianSortedArrays2(int[] nums1, int[] nums2) {
        int m = nums1.length;
        int n = nums2.length;
        //将两个数组合
        int tem[] = new int[m+n];
        //判断哪个比较长就将哪个先放入容器(减少移动的次数)
        if(m>=n){
            //将num1放入容器
            System.arraycopy(nums1,0,tem,0,m);
            //将num2插入数组
            insert(tem,nums2,m-1,0);
        }else{
            //将num2放入容器
            System.arraycopy(nums2,0,tem,0,n);
            //将num1插入数组
            insert(tem,nums1,n-1,0);
        }
        return (tem[(tem.length+1)/2-1]+tem[(tem.length+2)/2-1])/2.0;
    }
    public static void insert(int[] container,int[] arr,int border,int start){
        if(start>arr.length-1){
            return;
        }
        //查找插入的位置
        int targetIndex = findIndex(container,arr[start],border);
        //将数值插入
            //末尾插入
        if(targetIndex==border+1){
            container[border+1] = arr[start];
            insert(container, arr, border+1, start+1);
//            System.out.println(container);
        }else{
            //其他位置插入
            int temp[] = Arrays.copyOfRange(container,targetIndex,border+1);
            //向后挪一位
            System.arraycopy(temp,0,container,targetIndex+1,temp.length);
            //插入目标值
            container[targetIndex] = arr[start];
            insert(container, arr, border+1, start+1);
        }
    }
    //使用二分法查找目标数字最接近数字的下标
    public static int findIndex(int[] arr,int target,int border){
        int high = border;
        if(target>arr[high]){
            return high+1;
        }
        int low = 0;
        int mid = 0;
        while(low<=high){
            mid = (low+high)/2;
            if(arr[mid]==target){
                return mid;
            }
            if(arr[mid]>target){
                high = mid-1;
            }
            if(arr[mid]<target){
                low = mid+1;
            }
        }
        return low>high?low:mid;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Antgeek

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值