我们强烈建议您参考以下文章作为前提条件。
随机算法|第一组(介绍和分析)
随机算法|第2组(分类和应用)
在这篇文章中,讨论了蒙特卡洛算法。
问题陈述:给定一个n个数字且ε> 0的未排序数组A [],请计算其秩(在已排序A []中的位置)在[(1-ε)n / 2,(1 +ε)范围内的元素n / 2]。
对于½近似中值算法&epsilom;是1/2 =>等级应在[n / 4,3n / 4]范围内
我们可以在O(n)预期时间和O(n)最坏情况时间中找到第k个最小元素。
如果我们希望在不到O(n)的时间内允许较低的可能误差怎么办?
以下步骤表示一种算法,该算法的执行时间为O((Log n)x(Log Log n))次,并以不大于2 / n 2的概率产生错误的结果。
- 从数组中随机选择k个元素,其中k = c log n(c是一个常数)
- 然后插入一组。
- 对集合的元素进行排序。
- 返回集合的中值,即集合中的第(k / 2)个元素
C
/* C++ program to find Approximate Median using 1/2 Approximate Algorithm */ #include
using namespace std; // This function returns the Approximate Median int randApproxMedian(int arr[],int n) { // Declaration for the random number generator random_device rand_dev; mt19937 generator(rand_dev()); // Random number generated will be in the range [0,n-1] uniform_int_distribution distribution(0, n-1); if (n==0) return 0; int k = 10*log2(n); // Taking c as 10 // A set stores unique elements in sorted order set s; for (int i=0; i ::iterator itr = s.begin(); // Report the median of the set at k/2 position // Move the itr to k/2th position advance(itr, (s.size()/2) - 1); // Return the median return *itr; } // Driver method to test above method int main() { int arr[] = {1, 3, 2, 4, 5, 6, 8, 7}; int n = sizeof(arr)/sizeof(int); printf("Approximate Median is %d\n",randApproxMedian(arr,n)); return 0 }
Java
/* Java program to find Approximate Median using 1/2 Approximate Algorithm */ import java.util.Iterator; import java.util.Random; import java.util.TreeSet; class Test { static int arr[] = new int[]{1, 3, 2, 4, 5, 6, 8, 7} ; // This function returns the Approximate Median static int randApproxMedian(int n) { // Declaration for the random number Random r = new Random(); if (n==0) return 0; double k1 = 10*Math.log(n); // Taking c as 10 int k = (int)k1; // A treeset stores unique elements in sorted order TreeSet s = new TreeSet
(); for (int i=0; i itr = s.iterator(); int temp = s.size()/2 - 1; for (int i = 0; i < temp; i++) { itr.next(); } // Return the median return itr.next(); } // Driver method to test the above function public static void main(String[] args) { System.out.println("Approximate Median is " + randApproxMedian(arr.length)); } } Output:Approximate Median is 4
时间复杂度:
我们使用C++中STL提供的集合。在STL集中,每个元素的插入都为O(log k)。因此,对于k次插入,花费的时间为O(k log k)。
现在用c log n替换k
=> O(c log n(log(clog n)))=> O(log n(log log n))误差概率如何小于2 / n 2 ?
如果集合S至少有k / 2个元素来自左四分之一或右四分之一,则算法会出错。可视化此语句非常容易,因为我们报告的中位数将是第(k / 2)个元素,如果我们从左四分之一(或右四分之一)中取k / 2个元素,则中位数将是左四分之一(或右四分之一)。
数组可分为大小为n / 4的四个四分之一。因此,P(选择左四分之一)为1/4。那么,至少k / 2个元素来自左四分之一或右四分之一的概率是多少?此概率问题与以下相同:
给定一个硬币,使HEADS的概率为1/4,而TAILS的概率为3/4。硬币被扔了k次。我们至少得到k / 2个HEADS小于或等于的概率是多少?
解释:
If we put k = c log n for c = 10, we get P <= (1/2)2log n P <= (1/2)log n2 P <= n-2
从左四分之一中至少选择k / 2个元素的概率)<= 1 / n 2
从左或右四分之一中至少选择k / 2个元素的概率)<= 2 / n 2因此,算法产生的错误结果的概率小于或等于2 / n 2 。
参考: www.cse.iitk.ac.in/users/sbaswana/CS648/Lecture-2-CS648.pptx