字典序(今日头条2017秋招真题)
字典序(今日头条2017秋招真题)
给定整数n和m,将1到n的这n个整数按字典序排列之后,求其中的第m个数字。
对于n = 11,m = 4,按字典序排列依次为1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9,因此第4个数字为2。
输入
输入仅包含两个整数n和m。
样例输入
11 4
输出
输出仅包括一行,即所求排列中的第m个数字。
样例输出
2
时间限制
C/C++语言:1000MS其它语言:3000MS
内存限制
C/C++语言:65536KB其它语言:589824KB
package Test;
import java.util.Scanner;
public class Test5 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
long n = scan.nextLong(); //12248924213738476l;
long m = scan.nextLong(); //223284412422892l;
scan.close(); //10200955971180594
long k = 1; //answer,从1开始找
//十叉树
while (m > 0) {
long count = getCount(k, n); //以k开头且小于等于n的节点个数
if (count < m) { //第m个数不在k节点的分支上
m -= count; // 去掉k分支上小于n的节点
k++;// 当前节点设置为k右边第一个节点
} else {
m--; // 去掉k节点
if (m == 0) //第m个数是k节点
break;
k *= 10; //第m个数在k节点的分支上,当前节点设置为k节点分支最左节点,如1的下一层开始时10
//也就是进入更深一层的分支,比如我们已经知道它在1的分支上了,下一次就判断在不在10的分支上,再判断在不在100的分支上
}
}
System.out.println(k);
}
//返回此子树中以start开头且小于等于n的节点个数
//例如:start=1,n=20,则 cnt=11,节点依次为:1,10,11,12,13,14,15,16,17,18,19
private static long getCount(long start, long n) {
long base = 10, cnt = 1; //cnt个节点,1表示它本身
while (start * base <= n) { //下一层,10个数,再下,100...。这一步就是尝试着加0
if (start * base + (base - 1) <= n) { //最右节点小于n
cnt += base; //这一层全加
} else { //最左节点小于n或最右节点大于n,则只能加左边一部分
cnt += (n - base * start + 1);
}
base *= 10;
}
return cnt;
}
}

浙公网安备 33010602011771号