给定长度为N的未排序数组arr [] ,任务是找到该数组的中位数。
大小为N的排序数组的中位数在n为奇数时定义为中间元素,在n为偶数时定义为中间两个元素的平均值。
例子:
Input: arr[] = {12, 3, 5, 7, 4, 19, 26}
Output: 7
Sorted sequence of given array arr[] = {3, 4, 5, 7, 12, 19, 26}
Since the number of elements is odd, the median is 4th element in the sorted sequence of given array arr[], which is 7
Input: arr[] = {12, 3, 5, 7, 4, 26}
Output: 6
Since number of elements are even, median is average of 3rd and 4th element in sorted sequence of given array arr[], which means (5 + 7)/2 = 6
天真的方法:
- 以递增顺序对数组arr []进行排序。
- 如果arr []中的元素数为奇数,则中位数为arr [n / 2] 。
- 如果arr []中的元素数为偶数,则中位数为arr [n / 2]和arr [n / 2 + 1]的平均值。
有关以上方法的实现,请参考本文。
高效方法:使用随机QuickSelect
- 从arr []中随机选择枢轴元素,然后使用快速排序算法中的划分步骤,将所有小于枢轴的元素排列在其左侧,将大于枢轴的元素排列在其右侧。
- 如果在上一步之后,所选枢轴的位置在数组的中间,则它是给定数组的所需中间值。
- 如果位置在中间元素之前,则对子数组重复该步骤,从先前的起始索引开始,并选择枢轴作为结束索引。
- 如果位置在中间元素之后,则对子数组重复该步骤,从选定的枢轴开始,并在上一个结束索引处结束。
- 请注意,在偶数个元素的情况下,必须找到中间两个元素,并且它们的平均值将是数组的中位数。
下面是上述方法的实现:
C++
// CPP program to find median of
// an array
#include "bits/stdc++.h"
using namespace std;
// Utility function to swapping of element
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// Returns the correct position of
// pivot element
int Partition(int arr[], int l, int r)
{
int lst = arr[r], i = l, j = l;
while (j < r) {
if (arr[j] < lst) {
swap(&arr[i], &arr[j]);
i++;
}
j++;
}
swap(&arr[i], &arr[r]);
return i;
}
// Picks a random pivot element between
// l and r and partitions arr[l..r]
// around the randomly picked element
// using partition()
int randomPartition(int arr[], int l,
int r)
{
int n = r - l + 1;
int pivot = rand() % n;
swap(&arr[l + pivot], &arr[r]);
return Partition(arr, l, r);
}
// Utility function to find median
void MedianUtil(int arr[], int l, int r,
int k, int& a, int& b)
{
// if l < r
if (l <= r) {
// Find the partition index
int partitionIndex
= randomPartition(arr, l, r);
// If partion index = k, then
// we found the median of odd
// number element in arr[]
if (partitionIndex == k) {
b = arr[partitionIndex];
if (a != -1)
return;
}
// If index = k - 1, then we get
// a & b as middle element of
// arr[]
else if (partitionIndex == k - 1) {
a = arr[partitionIndex];
if (b != -1)
return;
}
// If partitionIndex >= k then
// find the index in first half
// of the arr[]
if (partitionIndex >= k)
return MedianUtil(arr, l,
partitionIndex - 1,
k, a, b);
// If partitionIndex <= k then
// find the index in second half
// of the arr[]
else
return MedianUtil(arr,
partitionIndex + 1,
r, k, a, b);
}
return;
}
// Function to find Median
void findMedian(int arr[], int n)
{
int ans, a = -1, b = -1;
// If n is odd
if (n % 2 == 1) {
MedianUtil(arr, 0, n - 1,
n / 2, a, b);
ans = b;
}
// If n is even
else {
MedianUtil(arr, 0, n - 1,
n / 2, a, b);
ans = (a + b) / 2;
}
// Print the Median of arr[]
cout << "Median = " << ans;
}
// Driver program to test above methods
int main()
{
int arr[] = { 12, 3, 5, 7, 4, 19, 26 };
int n = sizeof(arr) / sizeof(arr[0]);
findMedian(arr, n);
return 0;
}
Java
// JAVA program to find median of
// an array
class GFG
{
static int a, b;
// Utility function to swapping of element
static int[] swap(int[] arr, int i, int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
return arr;
}
// Returns the correct position of
// pivot element
static int Partition(int arr[], int l, int r)
{
int lst = arr[r], i = l, j = l;
while (j < r)
{
if (arr[j] < lst)
{
arr = swap(arr, i, j);
i++;
}
j++;
}
arr = swap(arr, i, r);
return i;
}
// Picks a random pivot element between
// l and r and partitions arr[l..r]
// around the randomly picked element
// using partition()
static int randomPartition(int arr[], int l, int r)
{
int n = r - l + 1;
int pivot = (int) (Math.random() % n);
arr = swap(arr, l + pivot, r);
return Partition(arr, l, r);
}
// Utility function to find median
static int MedianUtil(int arr[], int l, int r, int k)
{
// if l < r
if (l <= r)
{
// Find the partition index
int partitionIndex = randomPartition(arr, l, r);
// If partion index = k, then
// we found the median of odd
// number element in arr[]
if (partitionIndex == k)
{
b = arr[partitionIndex];
if (a != -1)
return Integer.MIN_VALUE;
}
// If index = k - 1, then we get
// a & b as middle element of
// arr[]
else if (partitionIndex == k - 1)
{
a = arr[partitionIndex];
if (b != -1)
return Integer.MIN_VALUE;
}
// If partitionIndex >= k then
// find the index in first half
// of the arr[]
if (partitionIndex >= k)
return MedianUtil(arr, l, partitionIndex - 1, k);
// If partitionIndex <= k then
// find the index in second half
// of the arr[]
else
return MedianUtil(arr, partitionIndex + 1, r, k);
}
return Integer.MIN_VALUE;
}
// Function to find Median
static void findMedian(int arr[], int n)
{
int ans;
a = -1;
b = -1;
// If n is odd
if (n % 2 == 1)
{
MedianUtil(arr, 0, n - 1, n / 2);
ans = b;
}
// If n is even
else
{
MedianUtil(arr, 0, n - 1, n / 2);
ans = (a + b) / 2;
}
// Print the Median of arr[]
System.out.print("Median = " + ans);
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 12, 3, 5, 7, 4, 19, 26 };
int n = arr.length;
findMedian(arr, n);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 program to find median of
# an array
import random
a, b = None, None;
# Returns the correct position of
# pivot element
def Partition(arr, l, r) :
lst = arr[r]; i = l; j = l;
while (j < r) :
if (arr[j] < lst) :
arr[i], arr[j] = arr[j],arr[i];
i += 1;
j += 1;
arr[i], arr[r] = arr[r],arr[i];
return i;
# Picks a random pivot element between
# l and r and partitions arr[l..r]
# around the randomly picked element
# using partition()
def randomPartition(arr, l, r) :
n = r - l + 1;
pivot = random.randrange(1, 100) % n;
arr[l + pivot], arr[r] = arr[r], arr[l + pivot];
return Partition(arr, l, r);
# Utility function to find median
def MedianUtil(arr, l, r,
k, a1, b1) :
global a, b;
# if l < r
if (l <= r) :
# Find the partition index
partitionIndex = randomPartition(arr, l, r);
# If partion index = k, then
# we found the median of odd
# number element in arr[]
if (partitionIndex == k) :
b = arr[partitionIndex];
if (a1 != -1) :
return;
# If index = k - 1, then we get
# a & b as middle element of
# arr[]
elif (partitionIndex == k - 1) :
a = arr[partitionIndex];
if (b1 != -1) :
return;
# If partitionIndex >= k then
# find the index in first half
# of the arr[]
if (partitionIndex >= k) :
return MedianUtil(arr, l, partitionIndex - 1, k, a, b);
# If partitionIndex <= k then
# find the index in second half
# of the arr[]
else :
return MedianUtil(arr, partitionIndex + 1, r, k, a, b);
return;
# Function to find Median
def findMedian(arr, n) :
global a;
global b;
a = -1;
b = -1;
# If n is odd
if (n % 2 == 1) :
MedianUtil(arr, 0, n - 1, n // 2, a, b);
ans = b;
# If n is even
else :
MedianUtil(arr, 0, n - 1, n // 2, a, b);
ans = (a + b) // 2;
# Print the Median of arr[]
print("Median = " ,ans);
# Driver code
arr = [ 12, 3, 5, 7, 4, 19, 26 ];
n = len(arr);
findMedian(arr, n);
# This code is contributed by AnkitRai01
C#
// C# program to find median of
// an array
using System;
class GFG
{
static int a, b;
// Utility function to swapping of element
static int[] swap(int[] arr, int i, int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
return arr;
}
// Returns the correct position of
// pivot element
static int Partition(int []arr, int l, int r)
{
int lst = arr[r], i = l, j = l;
while (j < r)
{
if (arr[j] < lst)
{
arr = swap(arr, i, j);
i++;
}
j++;
}
arr = swap(arr, i, r);
return i;
}
// Picks a random pivot element between
// l and r and partitions arr[l..r]
// around the randomly picked element
// using partition()
static int randomPartition(int []arr, int l, int r)
{
int n = r - l + 1;
int pivot = (int) (new Random().Next() % n);
arr = swap(arr, l + pivot, r);
return Partition(arr, l, r);
}
// Utility function to find median
static int MedianUtil(int []arr, int l, int r, int k)
{
// if l < r
if (l <= r)
{
// Find the partition index
int partitionIndex = randomPartition(arr, l, r);
// If partion index = k, then
// we found the median of odd
// number element in []arr
if (partitionIndex == k)
{
b = arr[partitionIndex];
if (a != -1)
return int.MinValue;
}
// If index = k - 1, then we get
// a & b as middle element of
// []arr
else if (partitionIndex == k - 1)
{
a = arr[partitionIndex];
if (b != -1)
return int.MinValue;
}
// If partitionIndex >= k then
// find the index in first half
// of the []arr
if (partitionIndex >= k)
return MedianUtil(arr, l, partitionIndex - 1, k);
// If partitionIndex <= k then
// find the index in second half
// of the []arr
else
return MedianUtil(arr, partitionIndex + 1, r, k);
}
return int.MinValue;
}
// Function to find Median
static void findMedian(int []arr, int n)
{
int ans;
a = -1;
b = -1;
// If n is odd
if (n % 2 == 1)
{
MedianUtil(arr, 0, n - 1, n / 2);
ans = b;
}
// If n is even
else
{
MedianUtil(arr, 0, n - 1, n / 2);
ans = (a + b) / 2;
}
// Print the Median of []arr
Console.Write("Median = " + ans);
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 12, 3, 5, 7, 4, 19, 26 };
int n = arr.Length;
findMedian(arr, n);
}
}
// This code is contributed by PrinciRaj1992
输出:
Median = 7
时间复杂度:
- 最佳案例分析:O(1)
- 平均案例分析:O(N)
- 最坏情况分析:O(N 2 )
想知道如何?
参考:斯坦福大学