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

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

题目描述

给定两个大小为 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++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

基于Redis有序集合实现滑动窗口限流的步骤

《基于Redis有序集合实现滑动窗口限流的步骤》滑动窗口算法是一种基于时间窗口的限流算法,通过动态地滑动窗口,可以动态调整限流的速率,Redis有序集合可以用来实现滑动窗口限流,本文介绍基于Redis... 滑动窗口算法是一种基于时间窗口的限流算法,它将时间划分为若干个固定大小的窗口,每个窗口内记录了该时间