Description
今天zyb参加一场面试,面试官听说zyb是ACMer之后立马抛出了一道算法题给zyb:
有一个序列,是1到n的一种排列,排列的顺序是字典序小的在前,那么第k个数字是什么?
例如n=15,k=7, 排列顺序为1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9;那么第7个数字就是15.
那么,如果你处在zyb的场景下,你能解决这个问题吗?
Input
T组样例(T<=100)
两个整数n和k(1<=n<=1e6,1<=k<=n),n和k代表的含义如上文
Output输出1-n之中字典序第k小的数字
Sample Input
1
15 7
Sample Output
15
方法一: (这个方法是在网上百度到的,太巧妙,一般想不出来)
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX=1e9+7;
const int MM=192600817;
deque <ll> dq;
int main()
{
ll T,n,m,i,j,k;
cin>>T;
while(T--)
{
cin>>n>>k;
ll x=1;
while(k>1)
{
if(x*10<=n)
{
x=x*10;
k--;
}
else
{
if(x+1<=n)
{
while(x%10==9)
x=x/10;
x++;
k--;
}
else
{
x=x/10;
while(x%10==9)
x=x/10;
x++;
k--;
}
}
}
cout<<x<<endl;
}
return 0;
}
方法二:直接暴力打表,按字符串排序之后,每次找的时候看与n的关系,如果比n大直接跳过,直到第k个数为止。
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX=1e6;
const int MM=192600817;
struct A
{
ll k;
char s[8];
}a[MAX+1];
bool cmp(struct A p,struct A q)
{
return strcmp(p.s,q.s)<0;
}
int main()
{
ll T,n,k,i,j;
for(i=1;i<=MAX;i++)
{
a[i].k=i;
ll t=i,e=0,m;
while(t)
{
a[i].s[e]=(t%10)+'0';
t/=10;
e++;
}
for(j=0;j<e/2;j++)
{
char tt;
tt=a[i].s[j];
a[i].s[j]=a[i].s[e-j-1];
a[i].s[e-j-1]=tt;
}
}
sort(a+1,a+MAX+1,cmp);
//cout<<a[1000].s<<endl;
cin>>T;
while(T--)
{
cin>>n>>k;
i=1;
for(i=1;i<=MAX;i++)
{
if(a[i].k>n)
continue;
else
k--;
if(k==0)
break;
}
cout<<a[i].k<<endl;
}
return 0;
}