一、区间贪心
解决区间不相交问题,给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间两两没有交集
思路:根据左端点从大到小排序,优先选择左端点最大的那个区间
#include<stdio.h>
#include<math.h>
#include<algorithm>
const int maxn=100;
using namespace std;
struct Interval
{
int x;
int y;
}I[maxn];
bool cmp(Interval a,Interval b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x>b.x;
}
int main()
{
int i,n;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&I[i].x,&I[i].y);
}
sort(I,I+n,cmp);
int count=1;
int lastX=I[0].x;
for(i=1;i<n;i++)
{
if(I[i].y<=lastX)
{
count++;
lastX=I[i].x;
}
}
printf("%d",count);
}
二、二分法(二分查找)
思路比较简单
注意点:
- mid=(left+right)/2中left+right可能会溢出,此时可以改为mid=left+(right-left)/2
- 两类变体:寻找有序序列中第一个>=指定元素x的元素位置;寻找有序序列中第一个>指定x的元素位置
三、二分法(函数零点、求近似值、装水问题)
double g(double x)
{
return x*x-2;
}
double solve(int L,int R)
{
int mid;
while (R-L>0.00001)
{
mid=(L+R)/2;
if(f(mid)>0)
{
R=mid;
}
else{
L=mid;
}
}
return mid;
}
四、快速幂
typedef long long LL;
#include<stdio.h>
LL binaryPow(LL a,LL b,LL m) //递归写法
{
if(b==0) return 1;
else if(b&1) //奇数
{
return a*binaryPow(a,b-1,m)%m;
}
else
{
LL ans=binaryPow(a,b/2,m);
return ans*ans%m;
}
}
LL binaryPow2(LL a,LL b,LL m) //迭代写法
{
LL ans=1;
while(b>0)
{
if(b&1) ans=a*ans%m;
else
{
a=a*a%m;
b>>=1;
}
}
return ans;
}
五、二路归并排序
const int maxn=100;
void merge(int A[],int L1,int R1,int L2,int R2)
{
int i=L1,j=L2;
int temp[maxn],index=0;
while(i<=R1&&j<=R2)
{
if(A[i]<=A[j])
{
temp[index++]=A[i++];
}
else
{
temp[index++]=A[j++];
}
}
while(i<=R1) temp[index++]=A[i++];
while(j<=R2) temp[index++]=A[j++];
for(i=0;i<index;i++)
{
A[L1+i]=temp[i]; //排序好的序列赋值回数组A(数组A从L1开始)
}
}
//将array数组的[left,right]区间进行排序
void mergeSort(int A[],int left,int right)
{
if(left<right)
{
int mid=(left+right)/2;
mergeSort(A,left,mid);
mergeSort(A,mid+1,right);
merge(A,left,mid,mid+1,right);
}
}
六、快速排序
#include<stdio.h>
int partition(int A[],int left,int right)
{
int temp=A[left];
while(left<right)
{
while(left<right&&A[right]>temp) right--;
A[left]=A[right];
while(left<right&&A[left]<temp) left++;
A[right]=A[left];
}
A[left]=temp;
return left;
}
void quickSort(int A[],int left,int right)
{
if(left<right)
{
int pos=partition(A,left,right);
quickSort(A,left,pos-1);
quickSort(A,pos+1,right);
}
}
七、随机选择算法
如何从一个无序的数组中求出第K大的数:
最直观:排序 O(nlogn)
而对于随机选择算法,可以达到O(n)的时间复杂度
再看这个算法,实际上使用了快速排序的一部分,没有完全做完的快速排序
//用于选择一组无序数中第K大的数
int randSelect(A[],int left,int right,int K)
{
if(left==right) return A[left];//递归边界
int p=randPartition(A,left,right);//快速排序中的主元
int m=p-left+1;
if(m==k) return A[p];
else if(m<k) return randSelect(A,p+1,right,K);
else return randSelect(A,left,p-1,K);
}