算法--------------------寻找两个有序数组的中位数

本文主要是介绍算法--------------------寻找两个有序数组的中位数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

给定两个大小为 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来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的解决方法:

package com.xinyu.test;/*** Created by zy on 2019/4/16.*/
public class TestArray13 {public static void main(String[] args) {System.out.println(findMedianSortedArrays(new int[]{1,2},new int[]{-1,3}));}/***** 寻找两个有序数组的中位数给定两个大小为 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*/public static double findMedianSortedArrays(int[] nums1, int[] nums2) {int length1 = 0,length2 = 0;if (nums1 != null) {length1 = nums1.length;}if (nums2 != null) {length2 = nums2.length;}if (length1 == 0 ) {if (length2 % 2 == 0) {return (double) (nums2[length2/2] + nums2[length2/2 -1]) / 2;}else {return (double)nums2[length2/2];}}if (length2 == 0){if (length1 % 2 == 0) {return (double)(nums1[length1/2] + nums1[length1/2 -1]) / 2;}else {return (double)nums1[length1/2];}}
//        if (nums1[0] > nums2[0]) {
//            return findMedianSortedArrays(nums2,nums1);
//        }
//        int all = length1 + length2;
//        if (all %2 ==0) {
//            return  (double)(nums1[length1 -1] + nums2[0]) / 2;
//        }else {
//            return (double)nums1[length1 -1] < (double)nums2[0] ? (double)nums1[length1 -1] : (double)nums2[0] ;
//        }int arr[] = new int[length1 + length2];for (int i = 0, j = 0 , q = 0;i < length1 || (j < length2);){if (i < length1 && j < length2){if (nums1[i] < nums2[j]) {arr[q++] = nums1[i++];}else {arr[q++] = nums2[j++];}}else if (i < length1){arr[q++] = nums1[i++];}else if (j < length2){arr[q++] = nums2[j++];}}int all = length1 + length2;if (all % 2 == 0) {return (double)(arr[all/2] + arr[all/2 -1]) / 2;}else {return (double)arr[all/2];}}}

网上的解决方法:

package com.xinyu.test;/*** Created by zy on 2019/4/16.*/
public class TestArray13 {public static void main(String[] args) {System.out.println(findMedianSortedArrays(new int[]{1,2},new int[]{-1,3}));}/***** 寻找两个有序数组的中位数给定两个大小为 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*/public static double findMedianSortedArrays(int[] nums1, int[] nums2) {int length = nums1.length + nums2.length;if (length % 2 == 1) {return findKth(nums1, 0, nums2, 0, length / 2 + 1);}int small = findKth(nums1, 0, nums2, 0, length / 2);int big = findKth(nums1, 0, nums2, 0, length / 2 + 1);return (small + big) / 2.0;}/**** @param nums1 数组1* @param index1 表示数组1从第几位开始找* @param nums2 数组2* @param index2  表示数组2 从第几位开始找* @param k  k表示要找第几位,注意k 代表的不是索引,是索引加1* @return*/private static int findKth(int[] nums1, int index1, int[] nums2, int index2, int k) {// 如果第一个数组查找的位置是末尾,那么说明要找的数据不再数组1里面,那么直接从数组2里面找就可以。if (index1 == nums1.length) {return nums2[index2 + k - 1];}// 如果第二个数组查找的位置是末尾,那么说明要找的数据不再数组1里面,那么直接从数组1里面找就可以。if (index2 == nums2.length) {return nums1[index1 + k - 1];}//如果要找当前第一位,那么直接返回当前两个数组的最小值if (k == 1) {return Math.min(nums1[index1], nums2[index2]);}// 找到第k  位对应的,两个数组的数值  每次排除掉k/2 个数int num1 = index1 + k / 2 - 1 < nums1.length ? nums1[index1 + k / 2 - 1] : Integer.MAX_VALUE;int num2 = index2 + k / 2 - 1 < nums2.length ? nums2[index2 + k / 2 - 1] : Integer.MAX_VALUE;// 如果数组1 的比较小,那么数组1的查找开始位置要往前挪动k/2 个位置(即一下子排除了k/2 个元素),同时要找的位置减去k/2//注意 数学里面的k - k / 2  和java 里面的k - k / 2 不是等值的if (num1 < num2) {return findKth(nums1, index1 + k / 2, nums2, index2, k - k / 2);}// 如果数组2 的比较小,那么数组2的查找开始位置要往前挪动k/2 个位置(即一下子排除了k/2 个元素),同时要找的位置减去k/2return findKth(nums1, index1, nums2, index2 + k / 2, k - k / 2);}}

个人看了大概二个小时,终于看懂了。

大概逻辑是这样:

首先确定是需要寻找一个数,还是寻找两个数,如果是一个数,那么寻找第K 位数返回就可以了,如果是找两个数,那么就调用两次方法找到,求平均值就可以了。

关键在于寻找第k 个数。两个数组,我要找第k 个数,那么我可以 直接排除k/2 个数。怎么排除呢?
因为是两个有序数组,那么我找两个数组的第k/2 位,谁的值小,那么谁所在的数组开始查找的索引位置,直接往前挪k/2个位置。因为要找的数,肯定不在这里面。
然后依次再找第k -k/2 个数,因为前面已经挪了k/2 个数,那么要找的第k 个数,其实是在k - k/2 个位置。继续递归往后找。
直到k == 1 ,那么取最小的一个值。因为要找的是比较小的一个。或者有一个数组已经没有元素可以找了,那么返回另外一个数组的index + k-1 的数就可以了。

二分法查找,确实快。不需要一个一个遍历!学到了。

这篇关于算法--------------------寻找两个有序数组的中位数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1131029

相关文章

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

C++原地删除有序数组重复项的N种方法

《C++原地删除有序数组重复项的N种方法》给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度,不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(... 目录一、问题二、问题分析三、算法实现四、问题变体:最多保留两次五、分析和代码实现5.1、问题分析5.

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.