算法很美——查找与排序

算法很美——查找与排序

递归习题

  • 题1:小白上楼梯
    题目描述:N阶,一次可以上1,2或3阶,有几种方法
    思路:f(n)=f(n-1)+f(n-2)+f(n-3)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//小白上楼梯
int fun(int m)
{
    if(m==0)return 1;
    if(m==1)return 1;
    if(m==2)return 2;
    return fun(m-1)+fun(m-2)+fun(m-3);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    printf("%d\n",fun(n));
    return 0;
}

  • 题2:旋转数组的最小数字
    旋转数组:把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转
    题目描述:输入一个递增排序后的数组的一个旋转,输出旋转数组的最小元素
    思路:二分法改造,且最小元素一定在无序的一边
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//旋转数组的最小数字
int fun(int a[],int l,int r)
{
    if(r==l+1)return a[r];
    int mid=(l+r)/2;
    if(a[mid]<a[l])fun(a,l,mid);
    else if(a[mid]>a[r])fun(a,mid,r);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        printf("%d\n",fun(a,0,n-1));
    }
    return 0;
}

在这里插入图片描述

  • 题3:在有空字符串的有序字符串数组中查找
    思路:二分查找

  • 题4:最长连续递增子序列
    思路:正常从左往右跑

  • 题5:设计一个高效的求a的n次幂的算法
    思路:a->a的平方->a平方的平方…

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//a的n次幂
int fun(int ans,int a,int n,int now)
{
    if(now==n)return ans;
    if(now*2>n)return ans*fun(a,a,n-now,1);
    fun(ans*ans,a,n,now*2);
}
int main()
{
    int a,n;
    while(scanf("%d %d",&a,&n)!=-1)printf("%d\n",fun(a,a,n,1));
    return 0;
}

快排

  • 单向扫描法

  • 双向扫描法

  • 三分法

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//快排
void swap(int a[],int i,int j)
{
    int k=a[i];
    a[i]=a[j];
    a[j]=k;
}
//单向扫描法
int partition1(int a[],int n,int l,int r)
{
    int pivat=a[l];
    int left=l+1;
    int right=r;
    while(left<=right)
    {
        while(left<=right&&a[left]<=pivat)left++;
        while(left<=right&&a[left]>pivat) swap(a,left,right--);
    }
    swap(a,l,right);
    return right;
}
//双向
int partition2(int a[],int n,int l,int r)
{
    int pivat=a[l];
    int left=l+1;
    int right=r;
    while(left<=right)
    {
        while(left<=right&&a[left]<=pivat)left++;
        while(left<=right&&a[right]>pivat)right--;
        if(left<=right)
        swap(a,left,right);
    }
    swap(a,l,right);
    return right;
}
 void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
}
//三分
void partition3(int a[],int n,int l,int r,int &c,int &d)
{
    int pivat=a[l];
    int left=l+1;
    int mid=l+1;
    int right=r;//printf("left=%d mid=%d right=%d\n",left,mid,right);
    while(mid<=right)
    {
        if(a[mid]<pivat)
            swap(a,left++,mid++);//printf("left=%d mid=%d right=%d\n",left,mid,right);print(a,n);}
        else if(a[mid]==pivat)mid++;//printf("left=%d mid=%d right=%d\n",left,mid,right);print(a,n);}
        else swap(a,mid,right--);//printf("left=%d mid=%d right=%d\n",left,mid,right);print(a,n);}
    }//printf("l=%d\n",l);
    swap(a,l,left-1);//print(a,n);printf("%d %d\n",left,right);
    c=left-1;
    d=right;
    return;
}

void QuickSort(int a[],int n,int l,int r)
{
    //print(a,n);
    if(r<l)return;
    //int q=partition2(a,n,l,r);//printf("%d\n",q+1);getchar();
    int c,d;
    partition3(a,n,l,r,c,d);
    //QuickSort(a,n,l,q-1);
    //QuickSort(a,n,q+1,r);
    //printf("%d %d\n",c,d);getchar();
    QuickSort(a,n,l,c-1);
    QuickSort(a,n,d+1,r);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        QuickSort(a,n,0,n-1);
        print(a,n);
    }
    return 0;
}


优化快排

  • 三点中值法
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//快排
void swap(int a[],int i,int j)
{
    int k=a[i];
    a[i]=a[j];
    a[j]=k;
}
//单向扫描法
int partition1(int a[],int n,int l,int r)
{
    int mid=(l+r)/2;
    if((a[l]<=a[mid]&&a[mid]<=a[r])||(a[r]<=a[mid]&&a[mid]<=a[l]))swap(a,l,mid);
    if((a[mid]<=a[r]&&a[r]<=a[l])||(a[l]<=a[r]&&a[r]<=a[mid]))swap(a,l,r);
    int pivat=a[l];
    int left=l+1;
    int right=r;
    while(left<=right)
    {
        while(left<=right&&a[left]<=pivat)left++;
        while(left<=right&&a[left]>pivat) swap(a,left,right--);
    }
    swap(a,l,right);
    return right;
}
//双向
int partition2(int a[],int n,int l,int r)
{
    int pivat=a[l];
    int left=l+1;
    int right=r;
    while(left<=right)
    {
        while(left<=right&&a[left]<=pivat)left++;
        while(left<=right&&a[right]>pivat)right--;
        if(left<=right)
        swap(a,left,right);
    }
    swap(a,l,right);
    return right;
}
 void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
}
//三分
void partition3(int a[],int n,int l,int r,int &c,int &d)
{
    int pivat=a[l];
    int left=l+1;
    int mid=l+1;
    int right=r;//printf("left=%d mid=%d right=%d\n",left,mid,right);
    while(mid<=right)
    {
        if(a[mid]<pivat)
            swap(a,left++,mid++);//printf("left=%d mid=%d right=%d\n",left,mid,right);print(a,n);}
        else if(a[mid]==pivat)mid++;//printf("left=%d mid=%d right=%d\n",left,mid,right);print(a,n);}
        else swap(a,mid,right--);//printf("left=%d mid=%d right=%d\n",left,mid,right);print(a,n);}
    }//printf("l=%d\n",l);
    swap(a,l,left-1);//print(a,n);printf("%d %d\n",left,right);
    c=left-1;
    d=right;
    return;
}

void QuickSort(int a[],int n,int l,int r)
{
    //print(a,n);
    if(r<l)return;
    //int q=partition2(a,n,l,r);//printf("%d\n",q+1);getchar();
    int c,d;
    int q=partition1(a,n,l,r);
    //partition3(a,n,l,r,c,d);
    QuickSort(a,n,l,q-1);
    QuickSort(a,n,q+1,r);
    //printf("%d %d\n",c,d);getchar();
    //QuickSort(a,n,l,c-1);
    //QuickSort(a,n,d+1,r);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        QuickSort(a,n,0,n-1);
        print(a,n);
    }
    return 0;
}


  • 绝对中值法:不常用
  • 待排序个数<=8时,用插入排序
    归并排序
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//归并排序
int n;
void merge(int a[],int l,int mid,int r,int helper[])
{

    int current=l,left=l,right=mid+1;
    while(left<=mid&&right<=r)
    {
        if(a[left]<=a[right])helper[current++]=a[left++];
        else helper[current++]=a[right++];
    }
    while(left<=mid)helper[current++]=a[left++];
    while(right<=r)helper[current++]=a[right++];
    for(int i=l;i<=r;i++)a[i]=helper[i];
}
void MergeSort(int a[],int l,int r,int helper[])
{
    if(l==r)return;
    int mid=(l+r)/2;
    MergeSort(a,l,mid,helper);
    MergeSort(a,mid+1,r,helper);
    merge(a,l,mid,r,helper);
}
int main()
{

    while(scanf("%d",&n)!=-1)
    {
        int a[n],helper[n];;
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        MergeSort(a,0,n-1,helper);
        for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
    }
    return 0;
}


归并、快排习题

  • 题1:奇数在左,偶数在右
    归并或快排思想
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//快排
void swap(int a[],int i,int j)
{
    int k=a[i];
    a[i]=a[j];
    a[j]=k;
}
//单向扫描法
int partition1(int a[],int n,int l,int r)
{
    if(a[l]%2==1)return l;
    int pivat=a[l];
    int left=l+1;
    int right=r;
    while(left<=right)
    {
        while(left<=right&&a[left]%2==1)left++;
        while(left<=right&&a[left]%2==0) swap(a,left,right--);
    }
    swap(a,l,right);
    return right;
}
void QuickSort(int a[],int n,int l,int r)
{
    //print(a,n);
    if(r<l||r==l)return;
    int q=partition1(a,n,l,r);//printf("%d\n",q+1);getchar();
    int c,d;
    //partition3(a,n,l,r,c,d);
    QuickSort(a,n,l,q-1);
    QuickSort(a,n,q+1,r);
    //printf("%d %d\n",c,d);getchar();
    //QuickSort(a,n,l,c-1);
    //QuickSort(a,n,d+1,r);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        QuickSort(a,n,0,n-1);
        for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
    }
    return 0;
}

  • 题2:第k小的数
    思路:第k小的数排序好后位置为k,用快排
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//快排
void swap(int a[],int i,int j)
{
    int k=a[i];
    a[i]=a[j];
    a[j]=k;
}
//单向扫描法
int partition1(int a[],int n,int l,int r)
{
    int pivat=a[l];
    int left=l+1;
    int right=r;
    while(left<=right)
    {
        while(left<=right&&a[left]<=pivat)left++;
        while(left<=right&&a[left]>pivat) swap(a,left,right--);
    }
    swap(a,l,right);
    return right;
}
void SelectK(int a[],int n,int l,int r,int k)
{
    if(l>r)return;
    //for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");getchar();
    int m=partition1(a,n,l,r);
    if(m==k-1){
        printf("%d\n",a[m]);
        return;
    }
    SelectK(a,n,l,m-1,k);
    SelectK(a,n,m+1,r,k);
}
int main()
{
    int n,k;
    while(scanf("%d %d",&n,&k)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        SelectK(a,n,0,n-1,k);

    }
    return 0;
}

  • 题3:超过一半的数字
    思路:O(n),相同+1,不同-1
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void fun(int a[],int n)
{
    int b=a[0],num=0;
    for(int i=1;i<n;i++)
    {
        if(a[i]==b)num++;
        else
        {
            if(num==0)b=a[i];
            else num--;
        }
    }
    printf("%d\n",b);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        fun(a,n);
    }
    return 0;
}

变化:正好一半
思路:最后一个是水王;最后一个不是水王,水王则是前n-1个的水王

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void fun(int a[],int n)
{
    int b=a[0],num=0,num2=1;
    for(int i=1;i<n-1;i++)
    {
        if(a[i]==a[n-1])num2++;
        if(a[i]==b)num++;
        else
        {
            if(num==0)b=a[i];
            else num--;
        }
    }
    if(num2==n/2){printf("%d\n",a[n-1]);return;}
    printf("%d\n",b);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        fun(a,n);
    }
    return 0;
}

  • 题4:最小可用id
    题目描述:在非负数组(乱序)中找到最小的可分配id(从1开始编号)数据量1000000,数组中为已分配id
    方法一:辅助数组
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void fun(int a[],int n)
{
    int helper[n+2];memset(helper,0,sizeof(helper));
    for(int i=0;i<n;i++)
    {
        if(a[i]<n+1)helper[a[i]]++;
    }
    for(int i=1;i<n+2;i++)if(helper[i]==0){printf("%d\n",i);return;}
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        fun(a,n);
    }
    return 0;
}

方法二:快排

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//快排
void swap(int a[],int i,int j)
{
    int k=a[i];
    a[i]=a[j];
    a[j]=k;
}
//单向扫描法
int partition1(int a[],int n,int l,int r)
{
    int pivat=a[l];
    int left=l+1;
    int right=r;
    while(left<=right)
    {
        while(left<=right&&a[left]<=pivat)left++;
        while(left<=right&&a[left]>pivat) swap(a,left,right--);
    }
    swap(a,l,right);
    return right;
}
void QuickSort(int a[],int n,int l,int r)
{
    if(r<l)
    {
        printf("%d\n",l+1);
        return;
    }
    int q=partition1(a,n,l,r);
    if(a[q]==q+1)QuickSort(a,n,q+1,r);
    if(a[q]>q+1)
    QuickSort(a,n,l,q-1);

}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        QuickSort(a,n,0,n-1);
    }
    return 0;
}

  • 题5:合并有序数组
    题目描述:给定两排序后的数组A,B,A末端有足够的缓冲空间容纳B,编写一个方法,将B合并入A并排序
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
}
void merge(int n,int m,int a[],int b[])
{
    int current=n+m-1,p1=n-1,p2=m-1;
    while(p1>=0&&p2>=0)
    {
        if(a[p1]>=b[p2])a[current--]=a[p1--];
        else a[current--]=b[p2--];
    }
    while(p1>=0)a[current--]=a[p1--];
    while(p2>=0)a[current--]=b[p2--];
    print(a,n+m);
}
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=-1)
    {
        int a[n+m];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        int b[m];
        for(int i=0;i<m;i++)scanf("%d",&b[i]);
        merge(n,m,a,b);
    }
    return 0;
}

  • 题6:逆序对个数
    题目描述:左大右小(逆序对不一定相邻)
    思路:归并,前半段有序,后半段有序;归并
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int ans;
void swap(int a[],int i,int j)
{
    int q=a[i];
    a[i]=a[j];
    a[j]=q;
}
void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
}
void fun(int a[],int l,int r,int n)
{
    if(l+1==r)
    {

        if(a[l]>a[r]){swap(a,l,r);
        ans++;}return;
    }
    if(l==r)return;
    fun(a,l,(l+r)/2,n);
    fun(a,(l+r)/2+1,r,n);
    int helper[n];
    int current=l,left=l,right=(l+r)/2+1;
    while(left<=(l+r)/2&&right<=r)
    {
        if(a[left]<=a[right]){helper[current++]=a[right++];}
        else {helper[current++]=a[left++];ans+=(r-right+1);}
    }
    while(left<=(l+r)/2)helper[current++]=a[left++];
    while(right<=r)helper[current++]=a[right++];
    for(int i=l;i<=r;i++)a[i]=helper[i];
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        ans=0;
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        fun(a,0,n-1,n);printf("%d\n",ans);
    }
    return 0;
}

堆排序
O(nlogn)

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

void swap(int a[],int i,int j)
{
    int q=a[i];
    a[i]=a[j];
    a[j]=q;
}
void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
}
void HeapAdjust(int a[],int n,int i)
{
    int j=2*i+1;
    if(j>=n)return;
    if(j+1<n&&a[j+1]<a[j])j++;
    if(a[j]<a[i]){swap(a,i,j);
    i=j;
    HeapAdjust(a,n,i);}
}
void HeapSort(int a[],int n)
{
    for(int i=n/2-1;i>=0;i--)HeapAdjust(a,n,i);
    for(int x=n-1;x>0;x--)
    {
        swap(a,0,x);
        HeapAdjust(a,x,0);
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        HeapSort(a,n);
        print(a,n);
    }
    return 0;
}


  • 计数排序
    辅助数组计数
    O(n+k)
    不适用于过稀疏的数组
    非负:长度max(n,max0+1)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;

void swap(int a[],int i,int j)
{
    int q=a[i];
    a[i]=a[j];
    a[j]=q;
}
void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
}
void CountSort(int a[],int n)
{
    int max0=a[0];
    for(int i=1;i<n;i++)if(a[i]>max0)max0=a[i];
    int helper[max(n,max0+1)];memset(helper,0,sizeof(helper));
    for(int i=0;i<n;i++)helper[a[i]]++;
    for(int i=0,current=0;i<max(n,max0+1);)
    {
        if(helper[i]){a[current++]=i;helper[i]--;}
        else i++;
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        CountSort(a,n);
        print(a,n);
    }
    return 0;
}

有负数

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

void swap(int a[],int i,int j)
{
    int q=a[i];
    a[i]=a[j];
    a[j]=q;
}
void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
}
void CountSort(int a[],int n)
{
    int max0=a[0],min0=a[0];
    for(int i=1;i<n;i++)if(a[i]<min0)min0=a[i];
    for(int i=1;i<n;i++)if(a[i]>max0)max0=a[i];
    int helper[max(n,max0+1-min0)];memset(helper,0,sizeof(helper));
    for(int i=0;i<n;i++)helper[a[i]-min0]++;
    for(int i=0,current=0;i<max(n,max0+1-min0);)
    {
        if(helper[i]){a[current++]=i+min0;helper[i]--;}
        else i++;
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        CountSort(a,n);
        print(a,n);
    }
    return 0;
}

桶排序
分配+收集
分配到一个桶中的数要进行排序,可用插入排序
由于每个桶中个数事先不确定,可用链表解决
O(n+n(logn-logm))
基数排序
类似桶排序,从低位开始,分配,收集到10个桶内
O(nk)

  • 题7:排序数组中找和的因子
    找二元组:
    方法一:二分法
    方法二:双指针
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int ans=0;
void seek(int a[],int l,int r,int p)
{
    if(r<l)return;
    int mid=(l+r)/2;
    if(a[mid]==p){ans++;return;}
    if(a[mid]<p)seek(a,mid+1,r,p);
    if(a[mid]>p)seek(a,l,mid-1,p);
}
//二分
void fun1(int a[],int n,int k)
{
    for(int i=0;i<n;i++)
    {
        seek(a,i+1,n-1,k-a[i]);
    }
}
//双指针
void fun2(int a[],int n,int k)
{
    int l=0,r=n-1;
    while(l!=r)
    {
        if(a[l]+a[r]>k)r--;
        if(a[l]+a[r]==k){ans++;l++;r--;}
        if(a[l]+a[r]<k)l++;
    }
}
int main()
{
    int n,k;
    while(scanf("%d %d",&n,&k)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        fun2(a,n,k);
        printf("%d\n",ans);
    }
    return 0;
}

找三元组:固定一个值得双指针

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int ans=0;
//双指针
void fun2(int a[],int n,int k,int i)
{
    int l=i+1,r=n-1;
    while(l<r)
    {
        if(l==i){l++;continue;}
        if(r==i){r--;continue;}
        if(a[l]+a[r]>k)r--;
        else if(a[l]+a[r]==k){printf("%d %d %d\n",a[i],a[l],a[r]);
                ans++;l++;r--;}
        else if(a[l]+a[r]<k)l++;
    }
}
int main()
{
    int n,k;
    while(scanf("%d %d",&n,&k)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<n;i++)
        fun2(a,n,k-a[i],i);
        printf("%d\n",ans);
    }
    return 0;
}
  • 题8:需要排序的子数组
    题目描述:给定无序数组,求需要排序的最短子数组长度
    顺序分升序,降序,由于未明确规定,以下代码默认为升序有序
    如规定升序降序都为有序,则分别按升序有序,降序有序找出最短子数组,再求最小
    降序最短子数组可逆序后找升序最短代替
    升序最短思路:从左到右找最高,比当前最高小的拓展为右边界;从右到左找最低,比当前最低大的拓展为左边界
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void fun(int a[],int n)
{
    int left=-1,right=-1;
    int max=a[0],min=a[n-1];
    for(int i=1;i<n;i++)
    {
        if(a[i]>max)max=a[i];
        if(a[i]<max)right=i;
    }
    for(int i=n-2;i>=0;i--)
    {
        if(a[i]<min)min=a[i];
        if(a[i]>min)left=i;
    }
    printf("%d %d\n",left,right);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        fun(a,n);
    }
    return 0;
}

  • 题9:TopK
    海量数据,求topk
    思路:从第k+1个数据开始,只需和前topk个数比较
    思路改进:用堆,大小为k,小顶堆。前k个数入数组,前k个数入后堆化,之后每次比较如小于堆顶,跳过;大于,调整堆
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void swap(int a[],int i,int j)
{
    int q=a[i];
    a[i]=a[j];
    a[j]=q;
}
void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d ",a[i]);printf("\n");
}
void HeapAdjust(int a[],int n,int i)
{
    int j=2*i+1;
    if(j>=n)return;
    if(j+1<n&&a[j+1]<a[j])j++;
    if(a[j]<a[i]){swap(a,i,j);
    i=j;
    HeapAdjust(a,n,i);}
}
int num=0;
void fun(int a[],int data,int k)
{
    if(num<k)
    {
        a[num++]=data;
        if(num==k)
        {
            for(int i=k/2-1;i>=0;i--)
            HeapAdjust(a,k,i);
            num++;
        }
    }
    else
    {
        if(data>a[0])
        a[0]=data;
        HeapAdjust(a,k,0);
    }
}
int main()
{
    int k;
    while(scanf("%d",&k)!=-1)
    {
        int a[k],data;
        while(scanf("%d",&data)!=-1&&data!=-1)
        fun(a,data,k);
        for(int x=k-1;x>0;x--)
        {
            swap(a,0,x);
            HeapAdjust(a,x,0);
        }
        print(a,k);
    }
    return 0;
}


partition和堆都能解决顺序统计量问题,堆更适用于海量数据流

  • 题10:所有员工年龄排序
    题目描述:n<=1000000,年龄取整
    思路:计数排序
    计数排序适用于数据范围小且已知
  • 题11:数组能排成的最小数(特殊排序)
    例如:
    输入:3,32,321
    输出:321323
    思路:采用快排,改比较方式
    比较方式:用字符串的比较,strcmp(s1+s2,s2+s1)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//快排
void swap(int a[],int i,int j)
{
    int k=a[i];
    a[i]=a[j];
    a[j]=k;
}
int fun(int a,int b)
{
    char str1[10],str2[10],s1[20],s2[20];
    memset(str1,'\0',sizeof(str1));memset(str2,'\0',sizeof(str2));memset(s1,'\0',sizeof(s1));memset(s2,'\0',sizeof(s2));
    itoa(a,str1,10);//把10进制整型a转化为字符串str1
    itoa(b,str2,10);
    strcat(s1,str1);strcat(s1,str2);
    strcat(s2,str2);strcat(s2,str1);
    return strcmp(s1,s2);
}
int partition1(int a[],int n,int l,int r)
{
    int pivat=a[l];
    int left=l+1;
    int right=r;
    while(left<=right)
    {
        while(left<=right&&fun(a[left],pivat)<=0)left++;//
        while(left<=right&&fun(a[left],pivat)>0) swap(a,left,right--);//
    }
    swap(a,l,right);
    return right;
}
 void print(int a[],int n)
{
    for(int i=0;i<n;i++)printf("%d",a[i]);printf("\n");
}
void QuickSort(int a[],int n,int l,int r)
{
    if(r<l)return;
    int q=partition1(a,n,l,r);
    QuickSort(a,n,l,q-1);
    QuickSort(a,n,q+1,r);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        int a[n];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        QuickSort(a,n,0,n-1);
        print(a,n);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值