数字字典序的第K小数字
原题在这里:
概述题意:给定数字n,在数字范围[1,n]中,找到根据字典序的第K小数字。
我首先想到的是构造,然后构造构造着就变成了dfs暴力(指严严实实地从第1小找到第k小)
然后因为1<=k<=n<=1e9,所以T了,然后就是考虑剪枝优化
因为时间关系就没考虑怎么剪枝了,直接看了题解,下次再做吧
my_code:
class Solution { int m, t, l; vector<int> num; int get() { int y = 0; for (int i = 0; i < l; ++i) y = y * 10 + num[i]; return y; } void dfs(int x) { // cout << t << "-> l==" << l << ", " << x << endl; --t; if (t && x * 10 <= m) ++l, dfs(x * 10); //优先扩充0 if (t && num[l - 1] < 9 && x < m) //增值进位 ++num[l - 1], dfs(get()); if (t && num[l - 1] == 9) num[--l] = 0; return; } public: int findKthNumber(int n, int k) { m = n, t = k, l = 1; num = vector<int>(10, 0); dfs(num[0] = 1); return get(); } };
其实我起初就是想的剪枝那方面的东西,但是我最优考虑还是能写暴力构造就写了,再去看题解的时候好歹没那么空脑袋
下面是官方的分析,运用字典树思想分析构造:

分析得很好,我的注解写在code里面了
code:
class Solution { int getsum(long x, long n) { //在树x下小于等于n的数量 long first = x, second = x + 1, sum = 0; /* first 表示x 分支左侧0开始的数字 second表示x+1分支左侧0开始的数字 second-first就表示当前层数的数量 如果当前数字first小于等于n那么还可以继续往下一层走 */ while (first <= n) { // cout << "x=" << x << ", sum+=" << min(n + 1, second) - first << endl; sum += min(n + 1, second) - first; //累计当层数量 first *= 10, second *= 10; //下层移动 } return sum; } public: int findKthNumber(int n, int k) { int x = 1; while (k > 1) { int sum = getsum(x, n); if (sum < k)//如果当前层sum小于k,那么应该x右移 k -= sum, ++x; else//否则x下移 --k, x *= 10; } return x; } };
【Over】

浙公网安备 33010602011771号