【中等】力扣算法题解析LeetCode357:统计各位数字都不同的数字个数

关注文末推广名片,即可免费获得本题测试源码

题目来源:LeetCode 357: 统计各位数字都不同的数字个数

问题抽象: 给定一个非负整数 n0 ≤ n ≤ 8),要求统计区间 [0, 10^n) 内所有 各位数字互不相同 的整数数量,满足以下核心需求:

  1. 数字表示规则

    • 数字按 十进制表示,忽略前导零(如 5 视为一位数 5,而非 05);
    • 数字长度可变:范围包含 1 位至 n 位整数(n=0 时仅含 0)。
  2. 互异性判定

    • 对任意整数,其 非前导零的实际各位数字 必须 全部不同(如 123 合法,122 非法);
    • 单数字(0 ≤ x ≤ 9)自动满足条件(无重复位)。
  3. 统计约束

    • 需高效计算 累计数量(非暴力枚举),时间复杂度 O(n)
    • 数学组合方法:
      • 长度为 k 的数字数量为 9 × P(9, k-1)(首位 1-9 选一,后 k-1 位从剩余 9 数字中排列);
      • 总数为所有 k ∈ [1, n] 的长度累加(k=0 时单独处理 0)。
  4. 边界处理

    • n=0 时,区间 [0,1) 仅含 0 → 输出 1
    • n=1 时,区间 [0,10)0-9 → 输出 10
    • n=2 时:
      • 一位数:0-910 个);
      • 两位数:首位 1-99 种),末位 0-9 排除首位(9 种)→ 81 个;
      • 总数 10 + 81 = 91
    • n=8 时,总数需精确计算(避免整数溢出)。

输入:非负整数 n0 ≤ n ≤ 8)。
输出:区间 [0, 10^n) 内各位数字互不相同的整数总数(整数值)。


解题思路

题目要求统计在区间 [0, 10^n) 内各位数字都不同的数字个数。可使用排列组合的思想高效求解:

  1. 边界处理:当 n = 0 时,只有数字 0,返回 1。
  2. 一位数处理:一位数(0-9)都满足条件,共 10 个。
  3. 多位数处理
    • 首位:不能为 0,有 9 种选择(1-9)。
    • 后续位:从剩余 9 个数字(0-9 除去首位数字)开始递减选择。
    • 公式:k 位数(k ≥ 2)的各位不同的数字个数为 9 × 9 × 8 × ... × (11 - k)
  4. 位数限制:当 n > 10 时,超过 10 位的数字必然有重复,只需计算到 10 位。
  5. 累加结果:从 1 位到 n 位,累加所有满足条件的数字个数。

代码实现(Java版)🔥点击下载源码

class Solution {
    public int countNumbersWithUniqueDigits(int n) {
        // 处理 n = 0 的情况
        if (n == 0) {
            return 1;
        }
        // 初始化结果:一位数(0-9)共10个
        int res = 10;
        // 超过10位无意义,限制 n 最大为10
        if (n > 10) {
            n = 10;
        }
        // base:当前位数的数字个数,初始为9(两位数首位9种选择)
        int base = 9;
        // available:剩余可用数字个数,初始为9(首位后剩余9个数字)
        int available = 9;
        // 从两位数开始计算到 n 位数
        for (int digits = 2; digits <= n; digits++) {
            base *= available; // 更新当前位数的数字个数
            res += base;       // 累加到结果
            available--;       // 可用数字减少1
        }
        return res;
    }
}

代码说明

  1. 边界处理:当 n = 0 时直接返回 1(只有数字 0)。
  2. 初始化res = 10 包含所有一位数(0-9)。
  3. 限制 n:若 n > 10,则设 n = 10(超过 10 位无有效解)。
  4. 循环计算
    • base 表示当前位数的有效数字个数,初始为 9(两位数首位 9 种选择)。
    • available 表示剩余可用数字,初始为 9(首位后剩余 9 个数字)。
    • 从两位数开始循环:
      • 更新 base = base × available(计算当前位数的数字个数)。
      • 累加 base 到结果 res
      • available 减 1(已用一个数字)。
  5. 返回结果:累加所有位数的有效数字个数。

提交详情(执行用时、内存消耗)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达文汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值