第二章作业

1.请用自然语言或伪代码描述找第k小的数的分治算法

运用分治法求解第k小的数的代码:

#include<iostream>
using namespace std;
int n,k;
int a[10000];
int cut(int left,int right)
{
    int t=a[left];
    int i=left+1,j=right;
    while(true)
    {
        while((i<=j)&&(a[i]<=t)) i++;
        while((i<=j)&&(a[j]>=t)) j--;
        if(i>j) break;
        swap(a[i],a[j]);
    }
    swap(a[left],a[j]);
    return j;
}
int fenzhi(int left,int right)
{
    if(left==right) return a[left];
    int u=cut(left,right);
    if((u+1)==k) return a[u];
    else if((u+1)>k) return fenzhi(left,u-1);
    else return fenzhi(u+1,right);
}
int main()
{
    cin>>n>>k;
    for(int i=0;i<n;i++) cin>>a[i];
    cout<<fenzhi(0,n-1);
}

    在代码中,调用函数fenzhi时,先判断left是否等于right,如果等于则代表数组只有一个数,这时直接返回这个数,否则则调用函数cut。在函数cut中,将传过去的数组的那一部分的第一个元素设做基准点,之后在基准点之后的第一个数和最后一个数进行检索。先从左往右找到第一个比基准点大的数,再从右往左找到第一个比基准点小的数之后交换这两个数的位置,继续重复这个过程,知道i比j大,则结束这个循环。此时i与i后面的数都比基准点大,j与j前面的数都比基准点小,这时交换a[j]与a[left]的值,再返回j,此时返回的数值就是基准点在数组中排第几大的位置-1。执行完函数cut之后重新回到fenzhi函数,并将函数cut返回的值赋值给u,如果u+1刚好等于我们要找的k,则返回a[u];如果u+1大于k,则证明我们找到的数太大,要从是一个基准点的左边继续找小一点的数,所以递归调用 fenzhi(left,u-1);如果u+1小于k,则证明我们找到的数太小,要从是一个基准点的右边继续找大一点的数,所以递归调用fenzhi(u+1,right)。一直递归调用下去直到(u+1)==k,则返回我们要找的第k大的数的数值。

2.分析该算法的最好时间复杂度和最坏时间复杂度

        该算法的核心在于利用快速排序实现,该算法在分解子问题时,需要将基准元素与每一个元素进行比较之后分出子问题,所以分解子问题的时间复杂度是O(n)

        最好时间复杂度:当基准元素刚好是元素序列中的中位数是,每个子问题的规模为原问题的2/1,且只有两个子问题,求解子问题的时间复杂度为2T(n/2),总的时间复杂度T(n)=O(n)+2T(n/2)=O(nlogn)。

        最坏时间复杂度:当基准元素恰好是最大值或者最小值时,会导致子问题的规模接近原问题,求解子问题的时间复杂度为T(n-1),总的时间复杂度T(n)=O(n)+T(n-1)=O(n^2)。

3.结合本章的学习,谈谈你对分治法的体会和思考

        分治法的基本思想是,把一个问题规模为n的问题分解成k个规模较小的子问题,每个子问题互相独立且解法与原问题相同,然后递归地求解子问题,最后将每个子问题的解相加得到原问题的解,

        运用分治法求解问题规模:(1)如果d>logba,T(n)=O(n^d),(2)如果d=logba,T(n)=O(logn*n^d),(3)如果d<logba,T(n)=O(n^(logba))。

        运用分治法可以有效地求解一些具有递归性质的问题,例如归并排序与快速排序。在问题规模较小时,分治法可以使得算法效率变高,但是在问题规模很大时,持续的递归调用会消耗大量资源,而且会使得算法的空间复杂度变得很大,在这样的情况下,算法整体效率反而会降低。因此我认为,分治法最适用的还是问题规模适中,且具有递归性质的问题。

        分治法这种将大问题分解成小问题的思想也可以有效地运用在其他算法之中,这样可以使得算法更加地清晰明了,也可以有效地提高算法效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值