📜  随机算法|组合3(1/2近似中位数)

📅  最后修改于: 2021-04-29 16:00:59             🧑  作者: Mango

我们强烈建议您参考以下文章作为前提条件。

随机算法|第一组(介绍和分析)
随机算法|第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的概率产生错误的结果。

  1. 从数组中随机选择k个元素,其中k = c log n(c是一个常数)
  2. 然后插入一组。
  3. 对集合的元素进行排序。
  4. 返回集合的中值,即集合中的第(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