分治思想的三个步骤:
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;