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

LeetCode 233:数字 1 的个数

LeetCode 233:数字 1 的个数

在这里插入图片描述

问题本质:统计数字规律

给定整数 n,计算 [0, n] 中所有整数里数字 1 出现的总次数。直接暴力遍历每个数统计会超时(n 可达 10^9),需通过数学规律逐位分析

核心思路:逐位贡献计算

对于数字 n每一位,分析该位上 1 出现的次数,最终累加所有位的结果。

关键观察:

将数字拆分为 高位(high)、当前位(cur)、低位(low),根据 cur 的值分三种情况计算该位的贡献:

  • 情况 1:cur < 1:该位的 1 由高位决定,贡献为 high × 10^pospos 是当前位的权值,如个位 pos=1,十位 pos=10)。
  • 情况 2:cur == 1:贡献为 high × 10^pos + low + 1(高位决定基础部分,低位补充剩余情况)。
  • 情况 3:cur > 1:贡献为 (high + 1) × 10^pos(高位加1,覆盖当前位为 1 的所有可能)。

算法步骤详解

步骤 1:初始化变量
  • ans:记录最终结果,初始为 0
  • mod:当前位的权值(如个位 mod=1,十位 mod=10,依次递增),初始为 1
步骤 2:逐位处理

循环处理每一位,直到 mod > n(覆盖所有位):

  1. 计算高位、当前位、低位

    • div = mod × 10(用于提取高位)。
    • high = n / div(当前位左侧的数字)。
    • cur = (n / mod) % 10(当前位的数字)。
    • low = n % mod(当前位右侧的数字)。
  2. 根据 cur 计算贡献

    • cur < 1:贡献为 high × mod
    • cur == 1:贡献为 high × mod + low + 1
    • cur > 1:贡献为 (high + 1) × mod
  3. 累加贡献并更新权值

    • ans += 贡献
    • mod *= 10(处理下一位,如从个位→十位→百位)。

完整代码(Java)

class Solution {public int countDigitOne(int n) {int ans = 0;long mod = 1; // 用long防止溢出(n≤1e9,mod最大为1e10,int会溢出)while (mod <= n) {long div = mod * 10;long high = n / div;long cur = (n / mod) % 10;long low = n % mod;if (cur < 1) {ans += high * mod;} else if (cur == 1) {ans += high * mod + low + 1;} else {ans += (high + 1) * mod;}mod *= 10;}return ans;}
}

关键细节解析

  1. 溢出处理
    mod 可能达到 10^10(当 n=1e9 时,mod 最终为 1e10),用 long 存储避免整数溢出。

  2. 位分解逻辑

    • divmod 的 10 倍,用于隔离高位(如 n=1234mod=10 时,div=100high=12)。
    • cur 通过 (n / mod) % 10 提取(如 mod=10 时,1234 / 10 = 123123 % 10 = 3,即十位的 3)。
    • low 通过 n % mod 提取(如 mod=10 时,1234 % 10 = 4,即个位的 4)。
  3. 示例验证

    • 示例 1(n=13
      • 个位(mod=1):cur=3>1,贡献 (1+1)×1=2(数字 111 的个位 1)。
      • 十位(mod=10):cur=1,贡献 0×10 + 3 + 1=4(数字 10111213 的十位 1)。
      • 总和 2+4=6,符合预期。

复杂度分析

  • 时间复杂度O(log n),仅需遍历 n 的位数(最多 10 位,10^9 是 10 位数)。
  • 空间复杂度O(1),仅用常数变量存储中间结果。

该方法通过数学规律逐位拆解,避免了暴力遍历的高复杂度,高效解决了大范围数字的统计问题,是处理“数字规律”类题目的经典思路。

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

相关文章:

  • Zero-Shot TrackingT0:对象分割+运动感知记——当“切万物”武士学会运动记忆,目标跟踪稳如老狗
  • 力扣面试150题--寻找旋转排序数组中的最小值
  • 互联网金融项目实战(大数据Hadoop hive)
  • 代码随想录算法训练营第五十三天|图论part4
  • Hive【Hive架构及工作原理】
  • Hive-vscode-snippets
  • 微信小程序文件下载与预览功能实现详解
  • nacos安装
  • SpringBoot配置多数据源多数据库
  • Androidstudio 上传当前module 或本地jar包到maven服务器。
  • 线性代数 上
  • Java 大视界 -- 基于 Java 的大数据分布式存储在工业互联网数据管理与边缘计算协同中的创新实践(364)
  • 从入门到进阶:JavaScript 学习之路与实战技巧
  • Nginx 安装与 HTTPS 配置指南:使用 OpenSSL 搭建安全 Web 服务器
  • Django集成Swagger全指南:两种实现方案详解
  • 探索 MyBatis-Plus
  • 智慧灯杆:不止于照明,塔能科技的城市感知网络野心
  • 解码3D格式转换
  • 多智能体(Multi-agent)策略模式:思维链CoT和ReAct
  • 万字解析Redission ---深入理解Redission上锁过程
  • 百度蜘蛛池解析机制:原创
  • ElementPlus:ElMessageBox增加type
  • iOS 加固工具实战解析,主流平台审核机制与工具应对策略
  • ESB 在零售,物流,制造,保险,医疗行业的应用方式
  • 【Linux/Ubuntu】VIM指令大全
  • Adv. Energy Mater.:焦耳热2分钟制造自支撑磷化物全解水电极
  • 基坑渗压数据不准?选对渗压计能实现自动化精准监测吗?
  • 戴尔电脑 Linux 安装与配置指南_导入mysql共享文件夹
  • 如何制定和落实ITIL 4服务请求的标准化与自动化策略
  • c# openxml 打开加密 的word读取内容