算法很美——查找与排序
递归习题
- 题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;
}