3.7排序&查找练习&时间空间复杂度

3.7排序&查找练习&时间空间复杂度

洛谷题目传送门

P1478 陶陶摘苹果(升级版)

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
struct T{ double x,y; }t[N];
bool cmp(T a, T b){ return a.y<b.y; }//自定义结构体排序
int main(){
    double n,s,a,b,ans=0; cin>>n>>s>>a>>b;//题目未给出数据类型,double保险
    for(int i=1; i<=n; i++) cin>>t[i].x>>t[i].y;
    sort(t+1, t+1+(int)n, cmp);//这里的n参数应当为整型,于是强制转换
    for(int i=1; i<=n; i++){
        if(t[i].x <= a+b && t[i].y<=s){ s-=t[i].y; ans++; }
    }
    cout<<ans<<endl;  return 0;
}

P1918 保龄球

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1;
struct T{ int id, value; }t[N];
bool cmp(T a, T b){ return a.value<b.value; }
int binSearch(T arr[], int n, int m){
    int l=1, r=n, mid;
    while(l<=r){
        mid=(l+r)/2;
        if(arr[mid].value<m) l=mid+1;
        else if(arr[mid].value>m) r=mid-1;
        else if(arr[mid].value==m) return arr[mid].id;
    } 
    return 0;
}
int main(){
    int n,v; scanf("%d", &n);
    for(int i=1; i<=n; i++){ scanf("%d", &v); t[i].id=i, t[i].value=v; }
    sort(t+1, t+n+1, cmp);   int q,m; scanf("%d", &q);
    while(q--){
        scanf("%d", &m);  printf("%d\n", binSearch(t, n, m)); 
    }  return 0;
}

P1678 烦恼的高考志愿

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1;
int a[N], b[N];
int binSearch(int arr[], int n, int m){
    int l=1,r=n, mid;
    while(l<r){//二分查找第一个不小于m的元素下标 r,注意没有等于了
        mid=(l+r)/2;
        if(arr[mid]<m) l=mid+1;
        else if(arr[mid]>=m) r=mid;
    }
    if(r>1 && abs(arr[r-1]-m) < abs(arr[r]-m)) r=r-1; //找差距最小的元素下标
    return r;
}
int main(){
    int m,n; cin>>m>>n; 
    for(int i=1; i<=m; i++) cin>>a[i];
    for(int i=1; i<=n; i++) cin>>b[i];
    sort(a+1, a+1+m);  long long ans=0;
    for(int i=1; i<=n; i++){
        int id = binSearch(a, m, b[i]);  ans += abs(a[id]-b[i]);
    }
    printf("%lld\n", ans);  return 0;
}

P2249 【深基13.例1】查找

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,m,a[N], b[N];
int binSearch(int* arr, int x){
    int l=1, r=n,mid;
    while(l<=r){
        mid=(l+r)/2;
        if(arr[mid]<x) l=mid+1;
        else if(arr[mid]>x) r=mid-1;
        else if(arr[mid]==x){
            if(mid>1 && arr[mid-1]==x) r=mid-1;
            else return mid;
        }
    }
    return -1;
}
int main(){
    cin>>n>>m;
    for(int i=1; i<=n; i++) cin>>a[i];
    for(int i=1; i<=m; i++) cin>>b[i];
    for(int i=1; i<=m; i++) printf("%d ", binSearch(a, b[i]));
    return 0;
} 

P1923 【深基9.例4】求第 k 小的数

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10;
int a[N], n, k;
void quickSort(int*arr, int l, int r){
    if(l>=r) return;
    int i=l, j=r, mid=arr[l];
    while(i<j){
        while(i<j && arr[j]>mid)  j--; a[i]=a[j];
        while(i<j && arr[i]<=mid) i++; a[j]=a[i];
    }
    a[i]=mid;
    if(k<=i-1) quickSort(arr, l, i-1); //只对答案区间进行排序
    if(k>=i+1) quickSort(arr, i+1, r);
}
int main(){
    scanf("%d%d", &n, &k);
    for(int i=0; i<n; i++) scanf("%d", &a[i]);
    quickSort(a, 0, n-1); // nth_element(a, a+k, a+n);
    printf("%d\n", a[k]);
    return 0;
} 

P7910 [CSP-J 2021] 插入排序

#include<bits/stdc++.h>//50分,超时
using namespace std;
const int N=1e4;
struct T{ int id, value; }a[N], b[N];
bool cmp(T a, T b){ return a.value<b.value; }
int find(T arr[], int n, T x){
    for(int i=1; i<=n; i++){
        if(arr[i].value==x.value && arr[i].id==x.id) return i;
    } 
    return -1;
}
void insertSort(T arr[], int n){
    for(int i=1; i<=n; i++){
        for(int j=i; j>=2; j--){
            if(arr[j].value < arr[j-1].value){
                T t = arr[j-1]; arr[j-1] = arr[j]; arr[j] = t;
            }
        }
    }
}
int main(){
    int n,q; scanf("%d%d", &n, &q);
    for(int i=1; i<=n; i++){ scanf("%d", &a[i].value); a[i].id=i; }
    for(int i=1; i<=q; i++){
        int f,x,v; scanf("%d%d", &f, &x);
        if(f==1){
            scanf("%d", &v); a[x].value=v;
        }else if(f==2){
            for(int i=1; i<=n; i++)    b[i]=a[i];
            insertSort(b, n);
            cout<<find(b, n, a[x])<<endl;
        }
    }
    return 0;
}

满分解法参考 CSP2021 J2/S2参考解析

时间复杂度&空间复杂度

在进行算法分析时,语句总的执行次数 \(T(n)\) 是关于问题规模n的函数,进而分析 \(T(n)\)\(n\) 的变化情况并确定 \(T(n)\) 的数量级。
算法的时间复杂度,也就是算法的时间量度,记作:\(T(n}=O(f(n))\), 这样的表示方法被称为大\(O\)表示法。
它表示随问题规模 \(n\) 的增大,算法执行时间的增长率和 \(f(n)\) 的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。
其中 \(f(n)\) 是问题规模n的某个函数。

\[f(n)=k,k为常数时,时间复杂度为O(1),可以称为常数阶。\\ f(n)=n时, 时间复杂度为O(n), 可以称为线性阶。\\ f(n)=logn时, 时间复杂度为O(logn), 可以称为对数阶。\\ f(n)=nlogn时,时间复杂度为O(nlogn),可以称为nlogn阶。\\ f(n)=n^2时, 时间复杂度为O(n^2), 可以称为平方阶。\\ f(n)=n^3时, 时间复杂度为O(n3), 可以称为立方阶。\\ f(n)=2^n时, 时间复杂度为O(2^n), 可以称为指数阶。\\ f(n)=n!时, 时间复杂度为O(n!), 可以称为阶乘阶。\\ f(n)=sqrt(n)时,时间复杂度为O(sqrt(n)),可以称为平方根阶\\ \]

算法时间复杂度:

\[O(1)<O(logn)<O(sqrt(n))<O(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!) \]

举例:对一个数据集中的N个元素进行排序,N<1e7。
当我们使用插入排序对数据集进行排序时,程序如下:

for(int i=1; i<=n; i++){       //执行次数:n 
    for(int j=i; j>1; j--){     //执行次数:n + n-1 + n-2 +...+ 1 = (1+n)*n/2
        if(arr[j]<arr[j-1]){
            int temp=a[j]; a[j]=a[j-1]; a[j-1]=temp;
        }
    }
}

上述程序总的执行次数:\(n+3*(1+n)*n/2 = O(n^2)\);这时候需要取大头 \(n^2\)
当N=1e7时,=1e14 > 5e8,故该算法不是正解,需要考虑其他的解法。

空间复杂度同样是对所在空间进行估计,但是由于程序的确定,那么一般空间大小就确定了,当然动态空间除外。
可以对所用空间的主要部分进行估算,不超过限制空间大小即可。sizeof(a)/1024.0/1024<<"MB";

posted @ 2021-12-11 23:04  HelloHeBin  阅读(118)  评论(0编辑  收藏  举报