来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order

题目描述

给定整数 n 和 k,返回  [1, n] 中字典序第 k 小的数字。

示例 1:

输入: n = 13, k = 2
输出: 10
解释: 字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。
示例 2:

输入: n = 1, k = 1
输出: 1

提示:

1 <= k <= n <= 109

解题思路

根据题意,最简单的方法是造一棵字典树,将1-n的数字全部存入,并且前序遍历所有数字,第k个就是答案,但是观察数据大小,应该会超时,果然就超时了。

通过观察,发现造出的字典树是一颗完全树,所以可以利用这个规律来虚拟字典上,并不需要真正造一颗树。对于结点i来说,i拥有的子树中结点个数为icount, 如果icount < k,那么寻找的结点不在这个子树中,寻找下一个相邻的结点,否则,寻找的结点就在这颗子树中,向下寻找i结点的每个子树。

由于字典树是满二叉树,所以求取i的结点数可以用虚拟的层次遍历,假设第j层左结点是x1,最右结点是x2,那么这一层的结点个数就是x2 - x1 + 1,下一层左结点x3 = x1 * 10, 右结点x4 = x2 * 10 + 9 或者 n。

代码展示

字典树 + dfs:


class Solution {
public:
    struct TreeNode
    {
        int val;
        TreeNode* ch[10];
        TreeNode(int val)
        {
            this->val = val;
            for (int i = 0; i < 10; i++)
            {
                this->ch[i] = NULL;
            }
        }
    };
    int miRet = 0;
    void dfs(TreeNode *root, int &k)
    {
        if (!root) return;
        k--;
        if (k < 0) return;
        if (k == 0)
        {
            miRet = root->val;
            return;
        }
        for (int i = 0; i < 10; i++)
            dfs(root->ch[i], k);
    }
    int findKthNumber(int n, int k) {
        TreeNode* root = new TreeNode(0);
        for (int i = 1; i <= n; i++)
        {
            TreeNode* p = root;
            string str = to_string(i);
            for (int j = 0; j < str.size(); j++)
            {
                if (p->ch[str[j] - '0'] == NULL)
                {
                    p->ch[str[j] - '0'] = new TreeNode(0);
                }
                p = p->ch[str[j] - '0'];
            }
            p->val = i;
        }
        int iTemp = k + 1;
        dfs(root, iTemp);
        return miRet;
    }
};
 

虚拟字典树+ 虚拟遍历:

class Solution {
public:
int MyCount(int i, long n)
{
int iCount = 0;
long iFirst = i;
long iLast = i;
while(iFirst <= n)
{
iCount += min(iLast, n) - iFirst + 1;
iFirst *= 10;
iLast = iLast * 10 + 9;
}
return iCount; } int findKthNumber(int n, int k) {
int iCur = 1;
k--;
while(k > 0)
{
int iCount = MyCount(iCur, n);
if(iCount <= k)
{
k -= iCount;
iCur++;
}
else
{
iCur *= 10;
k--;
}
}
return iCur;
}
};

运行结果

LeetCode-440 字典序的第K小数字的更多相关文章

  1. Java实现 LeetCode 440 字典序的第K小数字

    440. 字典序的第K小数字 给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字. 注意:1 ≤ k ≤ n ≤ 109. 示例 : 输入: n: 13 k: 2 输出: 10 解释: ...

  2. 440. 字典序的第K小数字 + 字典树 + 前缀 + 字典序

    440. 字典序的第K小数字 LeetCode_440 题目描述 方法一:暴力法(必超时) package com.walegarrett.interview; /** * @Author WaleG ...

  3. LeetCode 386——字典序的第 K 小数字

    1. 题目 2. 解答 字典序排数可以看做是第一层节点分别为 1-9 的十叉树,然后我们在树上找到第 K 小的数字即可.因此,我们需要分别统计以 1-9 为根节点的每个树的节点个数.如果 K 小于当前 ...

  4. 440 K-th Smallest in Lexicographical Order 字典序的第K小数字

    给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字.注意:1 ≤ k ≤ n ≤ 109.示例 :输入:n: 13   k: 2输出:10解释:字典序的排列是 [1, 10, 11, 1 ...

  5. [Swift]LeetCode440. 字典序的第K小数字 | K-th Smallest in Lexicographical Order

    Given integers n and k, find the lexicographically k-th smallest integer in the range from 1 to n. N ...

  6. 字典序的第K小数字

    今天zyb参加一场面试,面试官听说zyb是ACMer之后立马抛出了一道算法题给zyb:有一个序列,是1到n的一种排列,排列的顺序是字典序小的在前,那么第k个数字是什么?例如n=15,k=7, 排列顺序 ...

  7. Leetcode 440.字典序第k小的数字

    字典序第k小的数字 给定整数 n 和 k,找到 1 到 n 中字典序第 k 小的数字. 注意:1 ≤ k ≤ n ≤ 109. 示例 : 输入: n: 13 k: 2 输出: 10 解释: 字典序的排 ...

  8. Java实现 LeetCode 719 找出第 k 小的距离对(二分搜索法+二分猜数字)

    719. 找出第 k 小的距离对 给定一个整数数组,返回所有数对之间的第 k 个最小距离.一对 (A, B) 的距离被定义为 A 和 B 之间的绝对差值. 示例 1: 输入: nums = [1,3, ...

  9. [LeetCode] K-th Smallest in Lexicographical Order 字典顺序的第K小数字

    Given integers n and k, find the lexicographically k-th smallest integer in the range from 1 to n. N ...

  10. LeetCode 230.二叉树中第k小的元素

    题目: 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素. 说明:你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数. 这道题在leetCode上难 ...

随机推荐

  1. Docker进阶-Dockerfile建立一个自定义的镜像执行自定义进程

    前言 docker对我来说是一个很方便的工具,,上一篇文章也写了docker基本的一些使用,这篇文章重点描述一下Dockerfile的使用,从零建立一个自己定制化的镜像,并可以执行我们需要的任务. 作 ...

  2. Qt开发Active控件:如何使用ActiveQt Server开发大型软件的主框架(2)

    Qt开发Active控件:如何使用ActiveQt Server开发大型软件的主框架 注:本文更多地是带着如何去思考答案,而不是纯粹的放一个答案上来,如果你需要直接看到完整的答案,请直接看实例和最后的 ...

  3. 重学c#系列——linq(3) [二十九]

    前言 继续介绍一些复杂的linq. 正文 groupjoin 这个函数: 有department public class Deployment { public string Id { get; s ...

  4. C语言两结构体之间的成员互换

    今天在写一个通讯录实现程序的时候,遇到个让我突然卡壳的问题,不知道怎么进行两个结构体之间的成员互换......结构体成员有"姓名","性别","年龄& ...

  5. kafka详解(04) - kafka监控 可视化工具

    kafka详解(04) - kafka监控 可视化工具 Kafka监控Eagle 1)修改kafka启动命令 修改kafka-server-start.sh命令中 if [ "x$KAFKA ...

  6. Java类、对象以及(静态)方法的探讨

    大家好,这是我的第一篇博客.在这里我想跟大家分享一下Java最基础的Class and Object,也就是我们熟说的类和对象,以及对Java方法的探讨. 初学时的我因为没有对这里面的每一行代码思考透 ...

  7. (12)go-micro微服务JWT跨域认证

    目录 一 JWT介绍 二 JWT优缺点 三 JWT使用 1. 导包和数据定义 2.生成JWT 3.解析JWT 4.完整代码 四 最后 一 JWT介绍 JWT 英文名是 Json Web Token , ...

  8. 再讲Floyd变形:传递闭包类问题

    题目 今天上课老师讲到一道传递闭包的问题,由于蒟蒻之前讲的不详细再来讲一遍. 传送门 思路 建图,注意是有向图. 能确定名次指的是:在图上由这个点可以到达的点数+在图上可以到达这个点的点数=n-1 对 ...

  9. Hugging Face 2023 实习生招募计划

    Hugging Face 2023 实习生招募计划 想参与到 <王婆卖瓜>「最酷的 AI 社区」</王婆卖瓜>,共同构建未来吗?今天,我们为大家分享 Hugging Face ...

  10. forEach(遍历) VS map(映射) VS reduce(聚合)---学习笔记