当前位置: 首页 > news >正文

LeetCode 400 - 第 N 位数字

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

这道题看起来像是“在无限序列里随便数第 n 个字符”,但要做到O(1) 空间、O(d) 时间(d = 位数长度,通常 ≤ 10)并不是直接依次拼接数字就能高效做的。我们需要利用“按位段(1位、2位、3位……)”来跳过大量数字,定位到目标数字,然后从数字中取出对应那一位。本文用 Swift 给出清晰的实现、细致代码解析与示例测试,便于在工程中直接复用。

描述

考虑无限整数序列:

"1234567891011121314..."

给定整数 n(1 ≤ n ≤ 2³¹-1),返回该序列第 n 位上的数字(单个十进制数字 0–9)。

举例:

  • n = 3 → 第 3 位是 3
  • n = 11 → 序列前 11 个字符是 12345678910,第 11 位是 0(来自数字 10)

题解答案

核心思路分三步:

  1. 按位数分段跳过:先看 1 位数(1…9)共 9 个数,占 9×1 = 9 位;再看 2 位数(10…99)共 90 个数,占 90×2 位,依次类推,直到 n 落在当前位段中。
  2. 确定具体数字:假定 n 最终落在 digit 位数段,段起始数字为 start = 10^(digit-1),则第 (n-1)/digit 个数字(从 0 开始)即为目标数 num = start + (n-1)/digit
  3. num 中取第 (n-1) % digit 个数字(从左到右),返回它的数值。

实现要点:用 Int64 做中间计算以免乘法溢出(n 最大可达 2³¹-1),取位时可用字符串或数学方式。下面给出可运行的 Swift 实现。

题解代码分析

  • 主要变量:

    • n64:将输入 n 转为 Int64,方便大数运算。
    • digit:当前位数(从 1 开始)。
    • count:当前位数段的数字个数,例如当 digit = 2count = 90(10…99)。
    • start:当前段起始数字,如 1, 10, 100, ...
  • 循环:当 n64 > count * digit 时说明目标不在当前段,减去这段的总位数后进下一段。

  • 最终 numstart + (n64 - 1) / digit 计算。再从 num 中提取对应的位(使用字符串更直观,也足够快,位数 ≤ 10)。

下面是完整代码(包含注释与示例测试)。

import Foundationclass Solution {func findNthDigit(_ n: Int) -> Int {var n64 = Int64(n)var digit: Int64 = 1         // 当前数字位数(1 表示 1 位数)var count: Int64 = 9         // 当前位数的数字个数(1 位数有 9 个,2 位数有 90 个...)var start: Int64 = 1         // 当前位数段起始数字(1, 10, 100, ...)// 找到 n 落在哪个位数段while n64 > digit * count {n64 -= digit * countdigit += 1count *= 10start *= 10}// 在当前位段中,第 (n64-1)/digit 个数(从 0 开始)let offset = (n64 - 1) / digitlet num = start + offset    // 目标数字let indexInNum = Int((n64 - 1) % digit) // 在目标数字内的索引(从左到右,0-based)// 将 num 转为字符串,从中取出对应字符并返回其数值let s = String(num)let char = s[s.index(s.startIndex, offsetBy: indexInNum)]return Int(String(char))!}
}// 示例测试
let sol = Solution()
print(sol.findNthDigit(3))   // 输出: 3
print(sol.findNthDigit(11))  // 输出: 0
print(sol.findNthDigit(1))   // 输出: 1
print(sol.findNthDigit(9))   // 输出: 9
print(sol.findNthDigit(10))  // 输出: 1  (第 10 位是数字 '1',来自 10)
print(sol.findNthDigit(190)) // 测试边界附近:190 对应 100 的第一个数字 '1'

示例测试及结果

上面示例结果:

findNthDigit(3)   -> 3
findNthDigit(11)  -> 0
findNthDigit(1)   -> 1
findNthDigit(9)   -> 9
findNthDigit(10)  -> 1
findNthDigit(190) -> (根据运行结果)

你可以把上面的代码复制到 Xcode Playground 或 Swift REPL 里运行,会得到预期输出。

时间复杂度

  • 找到位数段时,digit 最多增长到 10(因为 64 位整数的位数远大于题目范围),循环次数是常数级别,整体时间复杂度为 O(1)(更准确地讲是 O(d),d 为位数,极小)。
  • 字符串转换和字符访问也是 O(d),d ≤ 10,所以总体非常快。

空间复杂度

  • 常数空间,主要开销是将 num 转成字符串,其长度 ≤ 10,空间复杂度 O(1)

总结

本题的关键在于不要去拼接整个无限序列,而是按“位段”跳跃定位。用 Int64 做中间计算以避免溢出,计算目标数字后取对应的字符即可。该方法简单、稳健、效率高,适合在工程场景中直接使用。若你需要进一步无字符串取位,也可以通过数学(整除/取余)实现,但字符串方式更直观、代码更简洁。

http://www.dtcms.com/a/491029.html

相关文章:

  • 团购网站开发的可行性分析营销推广渠道有哪些
  • SHA-256 算法
  • 淘宝网官方网站购物商城电子邮件免费注册
  • 网站策划薪资大型网站开发团队
  • 广西建设质监站官方网站成都装修公司招聘装修工人
  • 了解学习Python编程之python基础
  • html5 手机网站页面实例创建全国文明城市宣传栏
  • 10.16QT,mmm
  • 免费做长图网站商城源码价格低 质量好
  • YOLOv1/v2
  • 算法专题十二:二叉树的深搜
  • 建设旅游信息网站的好处职业学院网站建设
  • 【vue】设置时间格式
  • 泰安网站建设方案为网站做一则广告
  • 23种设计模式——状态模式(State Pattern)
  • 管理系统布局框架中都包含哪些要素?导航、面包屑、tab等
  • 制作企业网站的app如何做网校网站
  • 卷积值提取
  • [Android] Alarm Clock Pro 11.1.0一款经典简约个性的时钟
  • 【机器学习算法篇】K-近邻算法
  • K8S高可用集群-二进制部署 + nginx-proxy静态Pod版本
  • 使用Open CASCADE和BRepOffsetAPI_MakePipeShell创建螺旋槽钻头三维模型
  • 邯郸网站制作多少钱网站如何收录
  • 如何区分Android、Android Automotive、Android Auto
  • 企业融资方式有哪几种淄博网站seo价格
  • python - 第五天
  • 凡科网的网站建设怎么做网站 建设 公司
  • 透过浏览器原理学习前端三剑客:HTML、CSS与JavaScript
  • 镇江市网站建设江西省建设厅教育网站上查询
  • dede网站怎么设置首页相亲网站透露自己做理财的女生