有序数组中找中位数

问题描述

给定两个有序数组,返回这两个数组的中位数。如果中位数有两个,则返回它们的平均值。

e.g. [1, 3, 5]和[2, 4, 6]的中位数是3.5

解决思路

如果两个数组的长度之和为奇数,则中位数有一个;否则中位数为其中两个的平均值。

从两个数组中找第k个数,可以使用递归的思路。

程序

首先,写出在有序数组a和b中找到第k大的程序:

1. 利用归并排序中的merge数组方法,时间复杂度为O(k)。

	public int findKthNaive(int[] a, int[] b, int k) {
		int p1 = 0, p2 = 0;
		int i = 0;

		while (p1 < a.length && p2 < b.length) {
			if (i == k - 1) {
				return Math.min(a[p1], b[p2]);
			}
			if (a[p1] < b[p2]) {
				++p1;
			} else {
				++p2;
			}
			++i;
		}

		if (p1 == a.length) {
			return b[k - a.length - 1];
		}
		if (p2 == b.length) {
			return a[k - b.length - 1];
		}

		return -1;
	}

2. 如果两个数组的长度分别为m和n,则下面方法的时间复杂度为O(log(m+n)).

	public int findKthElemRec(int[] a, int a_start, int[] b, int b_start, int k) {
		if (a_start >= a.length) {
			return b[b_start + k - 1];
		}
		if (b_start >= b.length) {
			return a[a_start + k - 1];
		}

		if (k == 1) {
			return Math.min(a[a_start], b[b_start]);
		}

		int a_mid = a_start + k / 2 - 1 < a.length ? a[a_start + k / 2 - 1]
				: Integer.MAX_VALUE;
		int b_mid = b_start + k / 2 - 1 < b.length ? b[b_start + k / 2 - 1]
				: Integer.MAX_VALUE;

		if (a_mid < b_mid) {
			return findKthElemRec(a, a_start + k / 2, b, b_start, k - k / 2);
		} else {
			return findKthElemRec(a, a_start, b, b_start + k / 2, k - k / 2);
		}
	}

找中位数的程序只需要调用2即可

	public double findMedian(int[] a, int[] b) {
		int len1 = a == null ? 0 : a.length;
		int len2 = b == null ? 0 : b.length;
		int len = len1 + len2;

		if (len % 2 == 0) {
			return (findKthElemRec(a, 0, b, 0, len / 2) + findKthElemRec(a, 0,
					b, 0, len / 2 + 1)) / 2.0;
		} else {
			return findKthElemRec(a, 0, b, 0, len / 2 + 1);
		}
	}

  

时间: 2024-07-30 14:07:49

有序数组中找中位数的相关文章

剑指offer中在一个有序数组中找出和为s的两个数字

#include<iostream> using namespace std; bool findnumberwithsum(int A[],int length,int *num1,int *num2,int key) { if(NULL==A||length<=0||NULL==num1||NULL==num2) return false; int start=0; int end=length-1; int sum=0; while(start<end) { *num1=A[

找轮转后的有序数组中第K小的数

我们可以通过二分查找法,在log(n)的时间内找到最小数的在数组中的位置,然后通过偏移来快速定位任意第K个数. 此处假设数组中没有相同的数,原排列顺序是递增排列. 在轮转后的有序数组中查找最小数的算法如下: int findIndexOfMin(int num[],int n) { int l = 0; int r = n-1; while(l <= r) { int mid = l + (r - l) / 2; if (num[mid] > num[r]) { l = mid + 1; }

二分法计算有序数组中数字出现的次数

1. 问题描述 在给定的一个已经排好序的数组中,找出指定数字出现的次数.例如数组[1,2,3,4,4,4,4,6,8,9]中4出现的次数为4次. 2. 思路与方法 此问题可以在二分法的基础上进行改进.假设数组a为递增的数列,需要查找的数字为num,可以分别查找num在数组a中出现的起始位置和最后一次的位置,通过二者的差计算出数字num在数组a中出现的次数. c++代码如下: #include <stdio.h> #include <iostream> #include <st

leetcode | Median of Two Sorted Arrays 寻找2个有序数组中第k大的值

问题 Median of Two Sorted Arrays There are two sorted arrays A and B 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)). 分析 本题更经典通用的描述方式时: 给定2个有序数组,找出2个数组中所有元素中第k大的元素. 思路1 直观思

Leetcode 540.有序数组中的单一元素

有序数组中的单一元素 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数. 示例 1: 输入: [1,1,2,3,3,4,4,8,8] 输出: 2 示例 2: 输入: [3,3,7,7,10,11,11] 输出: 10 注意: 您的方案应该在 O(log n)时间复杂度和 O(1)空间复杂度中运行. 思路 取中间组坐标:mid = ( left + right ) / 2若 mid组中两元素相同 则唯一出现一次的元素必在 mid+1 组 到 right 组中(

C语言编程 在整型有序数组中查找想要的数字并且返回下标

遇到"有序"数组中查找元素类的题,优先考虑折半查找(二分查找) 做法核心是利用所定义的下标left和right与mid(由计算得来)下标的比较来逐渐缩短查找范围,达到一个阈值后即为找到. 源代码如下: #include<stdio.h> #include<stdlib.h> int search(int a[], int x, int left, int right)//定义二分查找函数 { while (left <= right) { int mid

两个有序数组,找第k小的数//未完

1.题目描述:a,b两个有序数组,找出第k小的数,logk,二分查找,1个小于怎么办? 2.思路: 对于数组A . B , 如果 B[pb] < A[pa] && B[pb] > A[pa - 1], 那么 B[pb] 一定是第 pa + pb + 1  小的数.比如数组A = {1, 8, 10, 20}, B = {5, 9, 22, 110},pa = 2, pb = 1, 这时,(B[pb] = 9) < (A[pa] =10) && (B[pb]

LeetCode 26 Remove Duplicates from Sorted Array (移除有序数组中重复数字)

题目链接: https://leetcode.com/problems/remove-duplicates-from-sorted-array/?tab=Description 从有序数组中移除重复数字,并且返回不重复数字的个数 遍历操作: 可以使用新的for循环 for (int n : nums){} 每次进行对比,并且更新第一个遇到不相等的元素的下标为i 对数组进行重新赋值操作 当数组长度大于1时,ans初值为1,当数组长度为0时,返回0 参考代码 : package leetcode_5

找到轮转后的有序数组中第K小的数

我们可以通过二分查找法,在log(n)的时间内找到最小数的在数组中的位置,然后通过偏移来快速定位任意第K个数. 此处假设数组中没有相同的数,原排列顺序是递增排列. 在轮转后的有序数组中查找最小数的算法如下: int findIndexOfMin(int num[],int n) { int l = 0; int r = n-1; while(l <= r) { int mid = l + (r - l) / 2; if (num[mid] > num[size]) { l = mid + 1;