【算法】快速排序 | 归并排序 | 二分查找

10 阅读3分钟

快速排序

  1. 主要思想:分治

  2. 稳定性:不稳定

  3. 时间复杂度:最好情况下image.png;最差情况下:image.png

  4. 解题步骤:

    1. 确定分界点 q[l]、q[(l+r)/2]、q[r] 随机 (l:左端点;r:右端点)
    2. 调整区间 分为两个区间,保证左区间的数都≤x ,右区间的数都≥x
    3. 递归处理左右两端 对两个区间按从小到大排序(左区间的最大值≤右区间的最小值)

    b6f5dbc03eb05606de53461e61649394.gif

    #include<iostream>
    using namespace std;
    
    const int N = 1e6+10;
    
    int n;
    int q[N];
    
    void quick_sort(int q[], int l, int r)
    {
        if(l>=r) return;   // 只含一个数的数组 / 空数组
        int x = q[l]; int i = l-1; int 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()
    {
        scanf("%d", &n);
        for(int i=0; i<n; i++) scanf("%d", &q[i]);
        quick_sort(q, 0, n-1);
        for(int i=0; i<n; i++) printf("%d", q[i]);
        return 0;
    }
    
    

归并排序

  1. 主要思想:分治

  2. 稳定性:稳定

  3. 时间复杂度:O(nlogn)

  4. 解题步骤:

    1. 确定分界点 mid=(l+r)/2
    2. 递归排序 left right
    3. 归并 合二为一

    image.png b6f5dbc03eb05606de53461e61649394.gif

    #include<iostream>
    using namespace std;
    
    const int N = 1e+10;
    
    int n;
    int q[N],tmp[N];
    
    void merge_sort(int q[], int l, int r)
    {
        if(l>=r) return;
        int mid = l+r >> 1; // 等同于 (l+r)/2
        merge_sort(q, l, mid), merge_sort(q, mid+1, r);
        
        int k = 0, i = l, j = mid + 1;
        while(i <= mid && j <= r)
        {
            if(q[i] <= q[j]) tmp[k++] = q[i++];
            else tmp[k++] = q[j++];
        }
        while(i <= mid) tmp[k++] = q[i++];
        while(j <= r) tmp[k++] = q[j++];
        
        for(int i = l,j = 0; i<=r; i++,j++) q[i] = tmp[j];
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 0; i<n; i++) scanf("%d",&q[i]);
        merge_sort(q,0,n-1);
        for(int i = 0; i<n ;i++) printf("%d",q[i]);
        return 0;
    }
    

二分查找

第二章:整数二分与浮点数二分(极限思想)-CSDN博客

整数二分

image.png

#include<iostream>
using namespace std;
const int N = 100010;
int n, m; // n:数组个数 m:查询次数
int q[N];
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 0; i<n; i++) scanf("%d", &q[i]);
    while(m--)
    {
        int x;
        scanf("%d", &x); // x:要查找的数
        
        // 寻找左边界
        int l = 0, r = n-1;
        while(l<r) // 当区间[l,r]被划分为[l,mid]和[mid+1,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) // 当区间[l,r]被划分为[l,mid-1]和[mid,r]时使用
            {
                int mid = l + r + 1 >> 1;
                if(q[mid] <= x) l = mid;
                else r = mid - 1;
            }
            cout<< l << endl;
        }
    }
    return 0;
}

浮点数二分

求某个数的平方根

#include<iostream>
using namespace std;
int main()
{
    double x;
    cin>>x;
    double l = -10000, r = 10000;
    while(r - l > 1e-8)
    {
        double mid = l + r >> 1;
        if(mid * mid >= x) r = mid;
        else l = mid;
    }
    printf("%lf\n", l);  // %f => float ; %lf => double,默认保留6位 ; %.2lf => 保留2位
    return 0;
}