分治法——归并排序,快速排序,二分模板

分治思想的三个步骤:
1、分解:把整个大问题分解成独立的子问题
2、解决:一般用递归解决问题
3、合并:把解决完的再合并回去

归并排序

1、如图,将数组通过递归一步一步分解单个元素
2、一边合并一边求解子问题,i,j 指向左右两个子序列的第一个数(详细解释都在代码里)
请添加图片描述
请添加图片描述

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <iomanip>
#include <queue>
#include <list>
#include <stack>

using namespace std;
typedef long long ull;

ull t,n,k,m,x,y;
ull a[500010];
ull b[500010];
ull ans;

void mmerge(int l,int mid,int r) //合并函数
{
    int i=l,j=mid+1;
    int x=0;
    while(i<=mid&&j<=r)//j-i为左边数组,r-j 为右边数组
    {
        if(a[i]>a[j])//左边大,则为逆序
        {
            b[x++]=a[j++];
        }
        else b[x++]=a[i++];
    }
    //一个子序列处理完,还剩另一个子序列需要处理
    while(i<=mid)//检查左半边
    {
        b[x++]=a[i++];
    }
    while(j<=r)//检查右半边
    {
        b[x++]=a[j++];
    }
    for(i=0;i<x;i++)//把排好的b复制回a数组
    {
        a[l+i]=b[i];
    }
}

void mergesort(int l,int r)//分解函数
{
    if(l<r)
    {
        int mid=(r+l)/2;
        mergesort(l,mid);
        mergesort(mid+1,r);
        mmerge(l,mid,r); //合并
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    ans=0;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    mergesort(0,n-1);
    for(int i=0;i<n;i++)  cout<<a[i]<<' ';
    cout<<endl;
    return 0;
}

快速排序

把序列分为左右两部分,使得左边的数都比右边的小;
即每次找一个基准数,比它小的放左边,比他大的放右边,每执行一次,都能找到这个基准数的正确位置;
然后再根据这个基准数,去排序他左边的数组,和右边的数组;
请添加图片描述

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <queue>
#include <list>

using namespace std;
int a[100010];
int n;
int part(int l,int r)
{
    int i=l;
    int t=a[r];
    for(int j=l;j<r;j++)
    {
        if(a[j]<t)
        {
            swap(a[i],a[j]);
            i++;
        }
    }
    swap(a[i],a[r]);
    return i;
}
void quicksort(int l,int r)
{
    if(l<r)
    {
        int i=part(l,r);//划分,找到i的正确位置
        quicksort(l,i-1);
        quicksort(i+1,r);
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    quicksort(0,n-1);
    for(int i=0;i<n;i++)
    {
        cout<<a[i]<<' ';
    }
    return 0;
}

//两边同时进行搜索的函数
void quicksort(int l,int r)
{
    if(l<r)
    {
        int t=a[l];
        int i=l,j=r;
        while(i<j)//两边同时进行
        {
            while(a[j]>t&&i<j) j--;//查找右半部分比t小的数
            a[i]=a[j];
            while(a[i]<=t&&i<j) i++;//查找左半部分比t大的数
            a[j]=a[i];
        }
        a[i]=t;//划分,找到t的正确位置
        quicksort(l,i-1);
        quicksort(i+1,r);
    }
    else return;
}

PS:做了一个快速排序的题,时间限制了,还不如sort(sort函数就是基于快速排序算法,并对于他的缺点做了很多优化);
快速排序可以用来解决特殊问题,灵活性比较强;

二分法

不细说啦
贴个模板

sort(a,a+n);
int left=0;
int right=a[n-1];
while(left<=right)
{
    mid=(left+right)/2;
    sum=0;
    for(int i=0;i<n;i++)
    {
        sum+=a[i]/mid;
    }
    if(sum>=m)   left=mid+1;
    else  right=mid-1;
}
cout<<left-1<<endl;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值