算法:
一:快排:
1.确定分界点
2.调整区间
3.递归处理左右两边
#include<iostream>
using namespace std;
const int N=100001;//注意分清数字范围(int)和数据范围
int n,q[N];
void quick_sort(int q[],int l,int r)
{
if(l>=r)return;//先排好序
int x=q[l],i=l-1,j=r+1;//1,定义两个指针,先向两边扩一位
//x=q[l+r>>1]
while(i<j)//2,迭代
{
do i++;while(q[i]<x);
do j--;while(q[j]>x);//边界不能写等于!!!
if(i<j)swap(q[i],q[j]);//两指针相遇时
}
quick_sort(q,l,j);//3
quick_sort(q,j+1,r);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>q[i];
quick_sort(q,1,n);//左闭右闭
for(int i=1;i<=n;i++)
cout<<q[i]<<' ';
}
法一:快排
#include<iostream>
using namespace std;
const int N=100001;
int n,k,q[N];
void quick_sort(int q[],int l,int r)
{
if(l>=r)return;
int x=q[l],i=l-1,j=r+1;
while(i<j)
{
do i++;while(q[i]<x);
do j--;while(q[j]>x);
if(i<j)swap(q[i],q[j]);
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
int main()
{
cin>>n>>k;
int i;
for(i=1;i<=n;i++)
cin>>q[i];
quick_sort(q,1,n);//左闭右闭
cout<<q[k];//直接输出第k个数
}
法二:sort
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,k,q[N];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>q[i];
sort(q+1,q+n+1);//sort一般是左闭右开(默认升序)
cout<<q[k];
}
/*#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,k,q[N];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>q[i];
sort(q,q+n+1);//sort(q+1,q+n+1);都可因为从1开始,0不用浪费了
cout<<q[k];
}*/
法三:nth_element
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,k,q[N];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>q[i];
nth_element(q,q+k,q+n+1);//左闭右开
//(数组名,数组名+第k个数,数组名+一共多少数加一)
/*nth_element的作用就是根据nth这个参数,
把容器内的元素分为2组,nth之前的都比它小,
nth之后的都比它大*/
cout<<q[k];
}
二:归并:
1.确定分界点
2.递归处理左右两边
3.归并:合二为一
/*归并:
(1)确定分界点
(2)递归处理左右两边
(3)归并:合二为一
*/
#include<iostream>//不理解了就记住每个比较都写等号,评论区大佬可留言
using namespace std;
const int N=1E5+10;
//int k;k不能定义成全局变量,不然每次使用时都会从0开始
int n,q[N],tmp[N];
void merge_sort(int q[],int l,int r)//闭区间[l,r]
{
if(l>=r)return;
int m=l+r>>1;//(1)m=l+r>>1与m=(l+r)/2的含义一样,都是向下取整
merge_sort(q,l,m);//(2)
merge_sort(q,m+1,r);
int k=0,i=l,j=m+1;//定义两个指针:i指向左边的起点,j指向右边的起点
while(i<=m&&j<=r)//(3)循环为空时停止(只要有一个里面的数用完了就停止)
if(q[i]<=q[j])tmp[k++]=q[i++];//比较q[i],q[j]值的大小,将小的放到tmp中
else tmp[k++]=q[j++];
while(i<=m)tmp[k++]=q[i++];//将多余的全部放入tmp
while(j<=r)tmp[k++]=q[j++];
for(int i=l,j=0;i<=r;i++,j++)
q[i]=tmp[j];//将数据存入q[i]
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>q[i];
merge_sort(q,1,n);
for(int i=1;i<=n;i++)
cout<<q[i]<<' ';
}
三:二分:
1.确定一个区间,使目标值在此区间中
2.找一个性质,这个性质具有二段性,答案是二段性的分界点
#include<iostream>
using namespace std;
const int N=1e5+10;
int n,m,q[N];
int main()
{
cin>>n>>m;//一共n个数,m个询问
for(int i=0;i<n;i++)
cin>>q[i];
while(m--)
{
int x;
cin>>x;
int l=0,r=n-1;//l,r写上边,mid写下边!!!
while(l<r)
{
int mid=l+r>>1;
if(q[mid]>=x)r=mid;
else l=mid+1;
}
if(q[l]!=x)cout<<"-1 -1"<<endl;
else
{
cout<<l<<' ';
int l=0,r=n-1;
while(l<r)
{
int mid=l+r+1>>1;
if(q[mid]<=x)l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
}
}
#include<iostream>
using namespace std;
int main()
{
double x;
cin>>x;
double l=-1000,r=1000;//
while(r-l>1e-8)
{
double mid=(l+r)/2;
if(mid*mid*mid>=x)//mid的值取大了,所以要把l往左移,缩小区间
r=mid;
else l=mid;
}
printf("%.6lf",l);
}