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

241 阅读2分钟

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

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

一、题目描述:

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

示例 1:

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

输入:n = 0 输出:1

提示:

0 <= n <= 8

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/co… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析:

  1. 这道题考察了什么思想?你的思路是什么?

    这道题目我的第一想法是暴力枚举,但是很有可能会超时。

    于是我继续观察这道题目,不重复?是不是没后一位就少一种可能!

    于是我马上动手。

    n为0时,x的个数为1,这个样例有提示,因为n大于1时,第一位不可能为0,所以我们n=1时,有10个。

  2. 做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?

    题目没读懂,我以为就是求n位的所有数字,结果还要求小于n位的所有位数的数字之和。

    后来仔细推导了样例才明白!!!!!

    大家要注意!

  3. 有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?

    我这种方法不是最优解,我看到了有大佬计算出递推公式,然后用递推法解决这道题目。

image.png

 class Solution {
 public:
     int countNumbersWithUniqueDigits(int n) {
         vector<int> dp(9, 0);
         dp[0] = 1;
         dp[1] = 10;
         for(int i=2; i<=n; i++){
             dp[i] = dp[i-1] + (dp[i-1]-dp[i-2])*(10-(i-1)); 
         }
         return dp[n];
     }
 };
 ​
 作者:aijun
 链接:https://leetcode-cn.com/problems/count-numbers-with-unique-digits/solution/by-aijun-9w89/
 来源:力扣(LeetCode)
 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

其实我觉得最强的解法是这种!

 class Solution:
     def countNumbersWithUniqueDigits(self, n: int) -> int:
         return [1, 10, 91, 739, 5275, 32491, 168571, 712891, 2345851][n]

哈哈哈哈哈哈哈哈哈,是不是很强的解法!

三、AC 代码:

 int countNumbersWithUniqueDigits(int n){
     if(n==0) return 1;
     if(n==1) return 10;
     int k=9,m=9;
     int res = 10;
     for(int i=1;i<n;i++){
         k*=(m--);
         res+=k;
     }
     return res;
 }

image.png

image.png

四、总结:

数学思维在解决算法题时往往能起到事半功倍的作用,我们的数学功底要扎实!