【LeetCode】357-统计各位数字都不同的数字个数

522 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

357. 统计各位数字都不同的数字个数

题目描述

给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 10^n

示例

示例一:
输入:n = 2
输出:91
解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。 

示例二:
输入:n = 0
输出:1

提示

0 <= n <= 8

题解

方法一

表哥我出来了喔~~(狗头.jpg)

public int countNumbersWithUniqueDigits(int n) {
  switch (n) {
    case 0:
      return 1;
    case 1:
      return 10;
    case 2:
      return 91;
    case 3:
      return 739;
    case 4:
      return 5275;
    case 5:
      return 32491;
    case 6:
      return 168571;
    case 7:
      return 712891;
    case 8:
      return 2345851;
    default:
      return 0;
  }
}

方法二

首先第一步,读懂题目,题目要求传入一个数字 n,返回从 0 到 10^n 之间(大于等于0,小于 10^n )各位数字都不同的数字个数。

例如输入 2,则返回 0 到 100 之间(大于等于 0,小于 100 )各位数字都不同的数字个数,需要排除 11,22,33,44,55,66,77,88,99。所以输入 2,返回91。

思路:

输入 0 时,数字有[0],则返回答案为 1

输入 1 时,数字有[0,1,2,3,4,5,6,7,8,9],则返回答案为 10

输入 2 时,这时候数字区间是 [0, 100),那么要一个个排列出来就很困难了,而到了后面就更不现实,所以就需要开始找规律了,已经知道 0 到 9 都是一位数,那么就从两位数开始,由于 0 不能作为第一位数,所以第一位数的就只能是 1~9。

当第一位数是 1 时,第二位数可以是:[0,2,3,4,5,6,7,8,9]

当第一位数是 2 时,第二位数可以是:[0,1,3,4,5,6,7,8,9]

当第一位数是 3 时,第二位数可以是:[0,1,2,4,5,6,7,8,9]

依次类推,可以发现,当第一位数字不一样时,第二位数字分别都有 9 种,那么从 10~99一共就有 9 * 9 = 81 个,然后再加上 0~9 的 10 个,就是:10 + 9 * 9 = 91

输入 3 时,这时候数字区间是 [0, 1000),同样的 0~99 的答案是 91,那么就直接从三位数开始就可以了。

当第一位数是 1 时,第二位数是 2 时,第三位数可以是:[0,3,4,5,6,7,8,9]

当第一位数是 1 时,第二位数是 3 时,第三位数可以是:[0,2,4,5,6,7,8,9]

当第一位数是 1 时,第二位数是 4 时,第三位数可以是:[0,2,3,5,6,7,8,9]

依次类推,可以发现,当第一位数是 0~9 时,第二位数有 9 种不同的选择,而当第一位和第二位确定后第三位数就只有 8 种不同的选择,这样就可以得出在三位数中一共有 9 * 9 * 8个,然后再加上 0~ 99 的 91 个,就是 91 + 9 * 9 * 8,也就是10 + 9 * 9 + 9 * 9 * 8

这样的话当 n = 4 时,答案为:10 + 9 * 9 + 9 * 9 * 8 + 9 * 9 * 8 * 7

整体规律:

n = 2:10 + 9 * 9 = 91

n = 3:10 + 9 * 9 + 9 * 9 * 8

n = 4:10 + 9 * 9 + 9 * 9 * 8 + 9 * 9 * 8 * 7

……

所以基于以上规律,可得到如下代码:

public int countNumbersWithUniqueDigits(int n) {
  // 当n=0和1时,直接返回
  if (n == 0) {
    return 1;
  }
  if (n == 1) {
    return 10;
  }
  int cur = 9;
  int res = 10;
  for (int i = 0; i < n - 1; i++) {
    cur *= 9 - i;
    res += cur;
  }
  return res;
}

代码详解:

cur 默认赋值 9,用于计算每一次递减的乘积,当循环时 i 递增,则 9 - i 就依次递减,然后与 cur 相乘得到每一轮的结果,最后将每一轮得到的 cur 加到 res,res 默认赋值 10,表示 n = 1 的答案为 10,再依次相加。