1 # given number n, see whether n has repeated number 2 def has_repeated(n): 3 str_n = str(n) 4 return len(set(str_n)) != len(str_n) 5 6 def permutation(n, k): 7 prod = 1 8 for i in range(k): 9 prod *= (n-i) 10 return prod 11 12 # calculate number of non-repeated n-digit numbers 13 # note: the n-digit number can't start with 0 14 # i.e: n_digit_no_repeat(2) calculates the non-repeated 15 # numbers in range [10, 99] (inclusive) 16 def n_digit_no_repeat(n): 17 if n == 1: 18 return 9 19 else: 20 return 9 * permutation(9, n-1) 21 22 class Solution(object): 23 def numDupDigitsAtMostN(self, N): 24 """ 25 :type N: int 26 :rtype: int 27 """ 28 N_str = str(N) 29 n_digit = len(N_str) 30 digits = list(map(int, N_str)) 31 result = N - 1 32 prefix = 0 33 for i in range(1, n_digit): 34 result -= n_digit_no_repeat(i) 35 for i in range(n_digit): 36 # when we fix the most significant digit, it 37 # can't be zero 38 start = 0 if i else 1 39 for j in range(start, digits[i]): 40 if has_repeated(prefix * 10 + j): 41 continue 42 if i != n_digit-1: 43 result -= permutation(10-i-1, n_digit-1-i) 44 else: 45 # optmized from `result -= has_repeated(prefix*10+j)` 46 result -= 1 47 prefix = prefix*10 + digits[i] 48 return result + has_repeated(N)
以下分析过程是我自己的思路,和上面的代码思路不太一样,具体的实现过程稍后补充,先把我的分析过程记录下来。
1位(0~9)有0个
2位(10~99)有9个:11,22,33,44,55,66,77,88,99
3位(100~999)有252个
百位以1~9开头,因为对于100~199的情况和200~299的情况都是一样的,因此外层用9相乘。
以100~199为例:
1.首先要找的个位和十位一样的:00,11,22,33,44,55,66,77,88,99,共10个。
2.找个位和百位一样的:01,11,21,31,41,51,61,71,81,91,共10个。
3.找十位和百位一样的:10,11,12,13,14,15,16,17,18,19,共10个。
但是2步中出现了数字11,3步中也出现了数字11,因此每一轮是10 + (10-1) + (10-1) = 28个,
因此外层9*28=252。
4位(1000~9999):有4464个
百位和千位单独考虑,是10~99:有9组包含重数字:11**,22**,33**,44**,55**,66**,77**,88**,99**。
这9组数字,因为前缀已经是重数,因此后面的**无论是多少都满足要求,这样就得到了9*100=900个。
接下来考虑10**~19**这10组,排除11**组之后,还剩9组。
分析如下:以10**为例:
1.首先找个位和十位一样的:00,11,22,33,44,55,66,77,88,99,共10个。
2.找个位和百位0一样的:00,10,20,30,40,50,60,70,80,90,共10个。
3.找个位和千位1一样的:01,11,21,31,41,51,61,71,81,91,共10个。
4.找十位和百位0一样的:00,01,02,03,04,05,06,07,08,09,共10个。
5.找十位和千位1一样的:10,11,12,13,14,15,16,17,18,19,共10个。
可以看到有重复计算的数字,因此第2步的00在第1步已经出现过,因此第2步是9个;
第3步有1个重复数字,剩下9个。第4步有2个重复数字,剩下8个,第5步有2个重复数字,剩下8个。
根据上面的分析可以知道,每一组有10 + (10-1) + (10-1) + (10-2) + (10-2)=44个。
因此从1000~1999这1000个数字中,有9*44=396个。再加上11**的100个,这样就是496个。
那么同样的计算方式,可以知道2000~2999也是496,从1000~9999一共就是9*496=4464个。
我尝试用这个思路来做一个解决方案,如果能完成,我会代码补充上。
leetcode上面的hard题目,如果自己有思路就尝试着写一下,如果没有思路就学习别人的。
算法的能力的提升,是一个循序渐进的过程,急不得。