第一讲 基础算法


1.快速排序

AcWing 785. 快速排序

https://www.acwing.com/problem/content/787/

点击查看代码
#include 
#include 
#include 
#include 
using namespace std;

const int N = 100010;
int a[N];
int n;
void quick_sort(int a[],int l,int r){
    if(l >= r) return;
    swap(a[l],a[(l+r) >> 1]);
    int pivot = a[l],i = l,j = r;
    // n = 100000 且 数字全都一样,那么普通写法时间复杂度为O(n)
    while(i < j){
        while(a[j] > pivot &&  i < j) j--;
        a[i] = a[j];
        if(i < j) i++;
        while(a[i] < pivot && i < j) i++;
        a[j] = a[i];
        if(i < j) j--;
    }
    a[i] = pivot;
    quick_sort(a,l,i-1);
    quick_sort(a,i+1,r);
}

int main(){
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    quick_sort(a,1,n);
    for(int i = 1; i <= n; i++) cout << a[i] << " ";


    return 0;
}

AcWing 786. 第k个数

https://www.acwing.com/problem/content/788/

点击查看代码
#include 
#include 
using namespace std;
const int N = 100010;
int a[N];
int n,k;

int quick_sort(int a[],int l,int r){
    if(l == r) return a[l];

    if(l < r){
        int pivot = a[l],i = l,j = r;
        while(i < j){
            while(a[j] > pivot && i < j) j--;
            a[i] = a[j];
            if(i < j) i++;
            while(a[i] < pivot && i < j) i++;
            a[j] = a[i];
            if(i < j) j--;
        }
        a[i] = pivot;
        if(i == k) return a[i];
        if(i > k) return quick_sort(a,l,i-1); // important
        if(i < k) return quick_sort(a,i+1,r);
    }
}

int main(){
    cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    
    cout << quick_sort(a,1,n) << endl;
    return 0;
}

2. 归并排序

AcWing 787. 归并排序

https://www.acwing.com/problem/content/789/

点击查看代码
#include 
using namespace std;

const int N = 100010;
int n;
int a[N];
void merge_sort(int a[],int l,int r){
    if(l >= r) return; 
    int mid = (l+r) >> 1;
    merge_sort(a,l,mid);
    merge_sort(a,mid+1,r);

    int i = l,j = mid+1;
    int b[r-l+2],k = 0;
    while(i <= mid && j <= r){
        if(a[i] <= a[j]) b[k++] = a[i++];
        else b[k++] = a[j++];
    }
    while(i <= mid) b[k++] = a[i++];
    while(j <= r) b[k++] = a[j++];
    for(int p = l,q = 0; p <= r; p++,q++){
        a[p] = b[q];
    }
}

int main(){
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    merge_sort(a,1,n);
    for(int i = 1; i <= n; i++) cout << a[i] << " ";
    return 0;
}

AcWing 788. 逆序对的数量

https://www.acwing.com/problem/content/790/

点击查看代码

#include 
using namespace std;
typedef long long LL;
const int N = 100010;
int n;
int a[N];
LL res;

void merge_sort(int a[],int l,int r){
    if(l >= r) return;
    int mid = (l + r)  >> 1;
    merge_sort(a,l,mid);
    merge_sort(a,mid+1,r);
    
    int k = 0,i = l,j = mid+1;
    int temp[r-l+2];
    while(i <= mid && j <= r){
        if(a[i] <= a[j]) temp[k++] = a[i++];
        else {
            temp[k++] = a[j++];
            res += mid-i+1;
        }
    }
    //扫尾
    while(i <= mid) temp[k++] = a[i++];
    while(j <= r) temp[k++] = a[j++];
    //物归原主
    for(int p = l,q = 0; p <= r; p++,q++){
        a[p] = temp[q];
    }
}

int main(){
    
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    merge_sort(a,1,n);
    cout << res << endl;
    
    
    return 0;
}

3.二分

点击查看代码

必须是 l <= r,
不然 a1,a2 mid = a1下标, a1可以找到 a2会找不到

int binary_search(int a[],int l,int r,int target){
    while(l <= r){
        int mid = l + (r-l)/2;
        if(a[mid] == target) return mid;
        if(a[mid] < target) l = mid + 1;
        else r = mid - 1;
    }
    return -1;
}

lower_bound

即 lower_bound:如果数组中存在和target相等的数,那么结果就是相等最左边的数,否则返回 > target最小的数的下标

点击查看代码
// a[l] > target, 当target最小,l == r会死循环
// a[l] == target, 找到了,跳出来
int l_b(int a[],int l,int r,int target){
    while(l <= r){
        int mid = l + (r-l)/2;
        if(l == r && a[l] >= target) break;
        if(a[mid] < target) l = mid + 1;
        else r = mid; //等于时取最左边
    }
    return l;
}

AcWing 789. 数的范围

https://www.acwing.com/problem/content/791/