2021-7-13算法复习(算法笔记119-141)

一、区间贪心

解决区间不相交问题,给出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);
}

二、二分法(二分查找)

思路比较简单
注意点:

  1. mid=(left+right)/2中left+right可能会溢出,此时可以改为mid=left+(right-left)/2
  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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值