zoukankan      html  css  js  c++  java
  • zyb的面试

    今天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
     
    就是求1-n的字典序排列的第几个
     
    一开始用递归来写   果然超时了
    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define LL long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define N 1e6+5
    
    int cnt;
    int m;
    void f(int n,int t)
    {
        if(n>t)
            return;
        ++cnt;
        if(cnt==m){printf("%d
    ",n);return;}
        rep(i,0,9)
        f(10*n+i,t);
    }
    int main()
    {
        int n;
        int cas;RI(cas);
        while(cas--)
        {
            cnt=0;
            RII(n,m);
            for(int i=1;i<=9;i++)
                f(i,n);
        }
    }
    View Code

    参考大神的方法:

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define LL long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    
    long getCntOfPre(long pre, long n)  // 计算以pre为开头并且小于n的数字的个数
    {
        long cnt = 1;
        long p = 10;
        for (; pre*p <= n; p *= 10)
            cnt += min(n, pre*p - 1 + p) - pre*p + 1;
        return cnt;
    }
    
    long solve(long n, long m)
    {
        long ans = 1;
        while (m != 0)
        {
            long cnt = getCntOfPre(ans, n);
            if (cnt >= m)
            {
                m--;
                if (m == 0)
                    break;  //  最终结果
                ans *= 10;      // 对应打头的数乘10,比如:原来是计算10打头的个数,现在要计算100打头的个数(缩小范围)
            }
            else
            {
                m -= cnt;  // 第m个数改为第m-cnt个数
                ans++;    // 对应打头的数加1,比如:原来是计算10打头的个数,现在要计算11打头的个数
            }
        }
        return ans;
    }
    
    int main()
    {
        long n, m;
        int q;RI(q);
        while (q--)
        {
            RII(n,m);
            cout << solve(n, m) << endl;
        }
        return 0;
    }
    View Code

    标准答案是用十叉树来做

     
     
     
     
     
  • 相关阅读:
    解决ecshop进入后台服务器出现500的问题
    Java8新特性(拉姆达表达式lambda)
    使用Optional优雅处理null
    Arrays.asList 存在的坑
    Java提供的几种线程池
    冒泡排序及优化详解
    如何让MySQL语句执行加速?
    关于https的五大误区
    127.0.0.1和0.0.0.0地址的区别
    宽带网络技术-大题重点
  • 原文地址:https://www.cnblogs.com/bxd123/p/10560555.html
Copyright © 2011-2022 走看看