算法导论第九章课后答案

这篇博客详细解答了《算法导论》第九章关于选择算法的多个习题,包括寻找第二小元素、同时找到最大值和最小值的比较次数下界、RANDOMIZED-SELECT的分析以及线性时间选择算法的讨论。内容涵盖了算法的数学证明、代码实现和最坏情况的时间复杂度分析。
摘要由CSDN通过智能技术生成

9.1-1 证明:在最坏情况下,找到n个元素中第二小的元素需要n+向上取整lgn-2次比较。

我们对于查找第2小元素分成2步。
step1:我们先将数组中的元素两两成对比较,共需n/2次比较,那么就有n/2个元素是较小的元素,然后再将这些较小的元素再次两两成对比较,又淘汰一半,重复这样的循环,每次淘汰一半元素直到只剩下1个元素,该元素就是最小元素。经过的比较次数为S=n/2+n/4+...(n/(2^k)=1) k=lgn S=n-1次。
step2:经过以上比较,就形成了一个二叉树,那么第2小的元素肯定与最小元素比较过,所以我们采取的方法是,从根结点也就是最小元素开始沿着根向叶子结点开始查找等于根节点的子结点A,第二小的元素就应该在与A结点属于同一个父结点的另外一个子结点B上,将B结点上的值给予第二小元素second,这样经过以上方式最坏lgn-1次比较,只要小于second值的元素,second就被覆盖成该元素,最终总能找到第2小元素。所以总比较次数为n-1+lgn-1=n+lgn-2。但是具体实现我还未想出来。

9.1-2 证明:在最坏情况下,同时找到n个元素中最大值和最小值的比较次数的下界是向上取整3n/2-2

我们将输入元素两两相互进行比较,然后把较小的与当前最小值比较,较大的与当前最大值比较,所以2个元素每次循环要比较3次,但是仅仅需要进行n/2次循环,所以总的比较次数为(向上取整)3n/2-2次。

以下是代码:

//同时求最小与最大值,只需要3n/2次比较
#include <iostream>
#include <time.h>
using namespace std;
const n=10;
void max_min(int A[],int &max,int &min)//同时找出最大值和最小值。
{
    for (int i=0;i<n;i+=2)
    {
        if (A[i]>A[i+1])
        {
            if (A[i]>max)
            {
                max=A[i];
            }
            if (A[i+1]<min)
            {
                min=A[i+1];
            }
        }
        else
        {
            if (A[i+1]>max)
            {
                max=A[i+1];
            }
            if (A[i]<min)
            {
                min=A[i];
            }
        }
    }
}
void main()
{
    //数组A max min全部置0
    int A[n]={0},max=0,min=0;
    //随机输入数组
    srand( (unsigned)time( NULL ) );
    for (int i=0;i<n;i++)
    {
        A[i]=rand()%100;
        cout<<A[i]<<" ";
    }
    cout<<endl;
    //max与min初始化
    if (n%2!=0)
    {
        max=A[0];
        min=A[0];
    }
    else
    {
        if (A[0]>A[1])
        {
            max=A[0];min=A[1];
        }
        else
        {
            max=A[1];min=A[0];
        }
    }
    //求数组A的max与min
    max_min(A,max,min);
    //输出max与min
    cout<<"max="<<max<<endl;
    cout<<"min="<<min<<endl;
}

9.2节代码:

#include <iostream>
#include <time.h>
using namespace std;
const n=8;
int PARTITION(int A[],int p,int r);
int RANDOM(int p,int r)
{
    int t=rand()%(r-p+1)+p;
    return t;
}
int RANDOMIZED_PARTITION(int A[],int p,int r)
{
    int i=RANDOM(p,r);
    swap(A[r],A[i]);
    return PARTITION(A,p,r);
}
int PARTITION(int A[],int p,int r)
{
    int x=A[r];
    int i=p-1;
    for (int j=p;j<=r-1;j++)//O(n)
    {
        if (A[j]<=x)
        {
            i++;
            swap(A[i],A[j]);
        }
    }
    swap(A[i+1],A[r]);
    return i+1;
}
int RANDOMIZED_SELECT(int A[],int p,int r,int i)
{
    if (p==r)
    {
        return A[p];
    }
    int q=RANDOMIZED_PARTITION(A,p,r);
    int k=q-p+1;
    if (i==k)
    {
        return A[q];
    }
    else if(i<k)
  
  • 7
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值