Day_15,期望为线性的选择算法之找到第position小的数

给你的脑子热热身:
Q1: 找到一个数组(互异)中的最大值
A1:

//伪代码
FindMax(arr)
max = arr[1]
for i=2 to arr.length()
	if arr[i] > max 
		max = arr[i]
return max

可以看出上面过程需要通过 arr.length()-1 次比较
Q2: 找到一个数组(互异)中的最大值和最小值,最少需要经过几次比较?
A2:
是不是一下子就想到,2(arr.length()-1)*,也就是设min、max
恭喜你答错了!
真实情况是需要 3*floor(n/2) 次比较, 思路是,取一对输入的元素,先将他们进行比较,然后将大的跟max比,将小的跟min比,这样一来 每两个元素只要进行3次 比较。
好了,如果你不信是最小的话,你取3个元素先比较看看咯,3个元素的话,每3个元素需要5次比较,效率是0.6,而2个元素是0.6666……其实就是因为[n(n+1)/2] / n = (n+1)/ 2 是一个单调递增函数

回归正题

#include<iostream>
#include<stdlib.h>
using namespace std;
//你们所熟悉的快速排序,但是这里只用了一个指针
//也可以如第一篇博客所写的那样采用两个指针(头尾)
int Partition(int *arr, int left, int right)
{
    int x = arr[right];
    int i = left -1;
    for (int j=left;j<right;j++)
    {
        if (arr[j]<=x)
        {
            i++;
            int temp = arr[i];
            arr[i]=arr[j];
            arr[j]=temp;
        }
    }
    int temp = arr[i+1];
    arr[i+1] = arr[right];
    arr[right] = temp;
    return i+1;
}

//
int Randomized_Partition(int *arr, int left, int right)
{
    //随机获得一个(left,right)之间的索引,打乱arr的顺序,让算法的运行时间不随arr本身的排序有较大的波动
    //并将这个索引的值作为 主元
    int i = rand()%(right-left)+left;
    int temp = arr[i];
    arr[i] = arr[right];
    arr[right] = temp;
    return Partition(arr,left,right);
}

//选择的核心
//算法核心思想,采用快速排序的思想,找到一个“主元”
//使其前面(包括自身)元素的个数len== position
//需要注意的点:
//1、如果position<len,则arr[position]在 “主元”前面的数组
//2、反之在主元后面的数组
int Randomized_Select(int *arr, int left, int right, int position)
{
    if (left==right)
        return  arr[right];
    int q = Randomized_Partition(arr,left,right);
    int len = q-left+1;
    if (position==len)
        return arr[q];
    else if (position<len)
        return Randomized_Select(arr,left,q-1,position);
    else
        return Randomized_Select(arr,q+1,right,position-len);
}

int main()
{
    int midNum;
    int data[10] = { 2,6,8,99,45,63,102,556,10,41 };
    midNum = Randomized_Select(data, 0, sizeof(data)/sizeof(*data)-1,5);
    cout << "midNum =" <<midNum;
    return 0;
}


上述方法的期望运行时间(由于输入是随机,因此求得的是期望时间)

对于元素互异数组 A={p…q…r}
首先要知道: 第q个元素之前(包含自身)正好有k个元素的概率是 1/n
定义指示器随机变量Xk
Xk = I {子数组[p…q]正好包含k个元素}
E[Xk] = 1/n
现在我们来求该方法运行时间的上界(小于等于这个界限)
1、k存在于[p,q-1]、[q+1,r]上,因为要求的是上界,因此假设数组A是最恶劣的单调递增。当q正好在k个元素时,可以得到
在这里插入图片描述
2、两边同时取期望得到
在这里插入图片描述
3、去除里面的max
在这里插入图片描述
4、使用替代法,同样因为求的是上界, 我们令E[T(n)]≤ cn,其中c是某个常数;O(n)≤ an,c是某个常数,上式继续转化为如下:
在这里插入图片描述
5、判断n的满足条件
在这里插入图片描述

=3= 推到过程打起来实在是太麻烦了!
有任何想法和见解十分欢迎私聊和评论,三人行必有我师!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值