題目以下:git
Given a positive integer
N
, return the number of positive integers less than or equal toN
that have at least 1 repeated digit.appExample 1:less
Input: 20 Output: 1 Explanation: The only positive number (<= 20) with at least 1 repeated digit is 11.
Example 2:spa
Input: 100 Output: 10 Explanation: The positive numbers (<= 100) with atleast 1 repeated digit are 11, 22, 33, 44, 55, 66, 77, 88, 99, and 100.
Example 3:code
Input: 1000 Output: 262
Note:blog
1 <= N <= 10^9
解題思路:題目要求出至少有一個重複元素的數字的總數,咱們能夠先求沒有重複元素的數字的總數,再用N減去這個總數便可。怎麼求出沒有重複元素的數字的個數呢?假設Input = 53254,首先求出位數小於Input時知足條件的數字總數input
位數爲1:一共有9種 (1,2,3.... 9)數學
位數爲2:最高位不能爲0,只能在1~9種任選一個,第二位在1~9中只有8種選擇,可是也能夠爲0,因此也是9選1,總數爲9*9,it
位數爲3:一共有 9 * 9 * 8 io
位數爲4:很明顯能夠看出規律了,總數爲9 * A(4-1,9) (A爲數學中排列)
位數等於Input時的狀況會麻煩一些。個人方法是首先求以5XXXX這種格式的總數,而後再求出53XXX這種格式的總數,直到最後求出總數。
5XXXX: 第二位只能爲0,1或者2,剩餘的位數中,只能在除了第一位和第二位以外的8個數字中挑選,總數爲 3 * A(3,8)
53XXX: 第三位只能爲0或者1,剩餘的位數中,只能在除了第一,二,三位以外的7個數字中挑選,總數爲 2 * A(2,7)
532XX以後的狀況相似
代碼以下:
class Solution(object): def numDupDigitsAtMostN(self, N): """ :type N: int :rtype: int """ def calcPerm(v1,v2): v = 1 while v1 > 0: v *= v2 v2 -= 1 v1 -= 1 return v ln = list(str(N)) res = 1 if len(list(str(N))) == len(set(list(str(N)))) else 0 #判斷N是否包含重複元素 dic_used = [int(ln[0])] for i in range(1,len(ln)): count = 0 for j in range(0,int(ln[i])): if j not in dic_used: count += 1 res += count * calcPerm(len(ln) - i - 1, 10 - i - 1) if int(ln[i]) in dic_used: break dic_used.append(int(ln[i])) # for i in range(1,len(ln)+1): if i != len(ln): res += (9 * calcPerm(i-1,9)) else: count = int(ln[0]) - 1 res += (count * calcPerm(i - 1, 9)) # return N - res