算法设计作业(三)

文章介绍了如何使用分治策略实现快速排序算法,该算法通过选取基准元素将序列分为两部分并递归排序。同时,文章还展示了如何运用分治法找到序列中的最大最小元素,以及利用分治策略求解幂运算问题,其中求x的n次方的时间复杂度为O(logn)。

学号:2020010944

 1. 快速排序算法是根据分治策略来设计的,简述其基本思想

思路:

    快速排序算法的基本思想是通过分治策略将一个待排序的序列分成两个子序列,其中一个子序列的所有元素都小于另一个子序列的所有元素。然后对这两个子序列分别进行快速排序,最后将两个子序列合并成一个有序的序列。算法的时间复杂度为O(nlogn)。

   具体实现时,我们首先选择一个基准元素,将序列中的元素分成两部分,一部分是小于基准元素的,另一部分是大于基准元素的。然后再递归地对这两部分进行快速排序,直到所有子序列的元素个数都不超过1。最后将所有子序列合并起来,就得到了一个有序的序列。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int a[N],n;
void quick(int a[],int l ,int r)
{
    if(l >= r) return ;
    int i = l - 1;
    int j = r + 1;
    int x = a[l + r >> 1];
    while(i < j)
    {
        do
        {
            i ++;
        } while (a[i] < x);
        do
        {
            j --;
        } while (a[j] > x);
        if(i < j)
        {
            swap(a[i],a[j]);
        }
        
    }
    quick(a,l,j);
    quick(a,j + 1,r);
}
/*
void quick_2(int a[],int l ,int r)
{

    if(l >= r) return;
    int tmp = a[l];
    int i = l,j = r;
    while(i < j)
    {
        while(a[j] > tmp && i < j) j --;
        if(i < j ) a[i++] = a[j];
        while(a[i] < tmp && i < j) i ++;
        if(i < j) a[j--] = a[i];
    }
    if(i == j) a[j] = tmp;
    quick_2(a,l,j);
    //cout << tmp << endl;
    //cout << i << " " << j << endl;
    quick_2(a,j + 1,r);

}
*/
int main()
{
    cin >> n;
    for(int i = 0;i < n;i ++)
        cin >> a[i];
    //quick_2(a,0,n-1);
    quick(a,0,n-1);
    for(int i = 0;i < n;i ++) cout << a[i] << " " ;
}

样例:

 

2.设计一个算法,采用分治法求一个整数序列中的最大最小元素。

思路

采用分治法求一个整数序列中的最大最小元素的算法如下:

  1. 如果序列只有一个元素,那么这个元素既是最大元素也是最小元素,直接返回。

  2. 如果序列有两个元素,比较这两个元素的大小,较小的为最小元素,较大的为最大元素,返回这两个元素。

  3. 如果序列有超过两个元素,那么将序列分成两个子序列,分别对这两个子序列递归调用本算法,得到它们的最大最小元素。

  4. 比较这两个子序列的最大最小元素,得到整个序列的最大最小元素。

算法的时间复杂度为O(nlogn)。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
int n,a[N];
struct A
{
    int maxx;
    int minn;
};

A max_min(int a[],int l,int r)
{
    A res,res_l,res_r;
    if(l == r)
    {
        res.maxx = a[l];
        res.minn = a[l];
    }
    else if(l + 1 == r)
    {
        res.maxx = max(a[l],a[r]);
        res.minn = min(a[l],a[r]);
    }
    else
    {
        int mid = (l + r) >> 1;
        res_l = max_min(a,l,mid);
        res_r = max_min(a,mid + 1,r);
        res.maxx = max(res_l.maxx,res_r.maxx);
        res.minn = min(res_l.minn,res_r.minn);
    }
    return res;
}

int main()
{
    cin >> n;
    for(int i = 0;i < n;i ++) cin >> a[i];
    A res = max_min(a,0,n-1);
    cout << "MAX: " << res.maxx << endl;
    cout << "MIN: " << res.minn << endl;
    return 0;
}

样例

3.设计一个算法,采用分治法求 ^{x^{n}}

 思路

求x的n次方可以采用分治法来实现,其基本思路如下:

  1. 递归结束条件:当n=0时,^{x^{n}}=1,当n=1时,^{x^{n}}​=x。

  2. 将问题分解为规模更小的子问题:对于任意n>1,可以将^{x^{n}}​分解为^{x^{n/2}} * ^{x^{n/2}} (当n为偶数时)或 ^{x^{n/2}} * ^{x^{n/2}} * x(当 n为奇数时)

  3. 递归求解子问题:对于 ^{x^{n/2}} ,直接递归求解即可。 

  4. 合并子问题的解:将 ^{x^{n/2}} 的计算结果合并起来,得到^{x^{n}}的解。

时间复杂度为O(\log_{2} n)

代码: 

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
typedef long long ll;
ll x,n,res;
ll Pow(int x,int n)
{
    if(n == 0) return 1;
    else if(n % 2 == 0)
        return Pow(x,n/2) * Pow(x,n / 2);
    else if(n % 2 != 0)
        return Pow(x,(n-1) / 2) * Pow(x,(n - 1) / 2) * x;
}
int main()
{
    cin >> x >> n;
    res = Pow(x,n);
    cout << res << endl;
    return 0;
}

样例

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值