1. 程式人生 > >算法66------計算各個位數不同的數字個數【動態規劃】

算法66------計算各個位數不同的數字個數【動態規劃】

return 輸入 輸出 位數 滿足 number div unique pan

一、題目:計算各個位數不同的數字個數

給定一個非負整數 n,計算各位數字都不同的數字 x 的個數,其中 0 ≤ x < 10n

示例:

輸入: 2
輸出: 91 
解釋: 答案應為除去 11,22,33,44,55,66,77,88,99 外,在 [0,100) 區間內的所有數字。

思路:動態規劃

dp[i]表示 i 位數範圍內【0,10^i】各位數字都不同的數字 x 的個數。

  • 當 n = 1 時, 只有 0 符合條件, 當 n = 10 時, 0 - 9 符合條件 (10個);
  • 當 n >= 2 時,記 f( n )為 [ 0, 10^n )範圍內滿足條件的數值個數,記 g( k ) 為 k位數中滿足條件的數值個數, 則 f(n) = g(1) + g(2) + g(3) + ... +g(n) = f (n - 1) + g (n),

而 g(n) 屬於組合問題, g(n) = 9 * 9 * 8 * 7 *...... * (11 - n),第一個“9”代表最高位上可選擇的數為“ 1 ~ 9”九個,0 不可選,第二個“9”代表第二位上可選擇的數為“0 ~ 9”中除去高位所選的其他九個數,依次類推,第 n 位上可選的數有 ( 11 - n ) 個。

即,dp[0] = 10,dp[0]表示n=1時,結果是10

dp[1] = 91,dp【1】表示n = 2時,結果為dp[0] + 9*9 = 91

dp[2] = 739,dp【2】表示n=3時,結果為dp[1] + 9 * 9 * 8 = 91 + 648 = 739

代碼:

def countNumbersWithUniqueDigits(n):
    if n == 0:
        return 1
    dp = [0] * n
    dp[0] = 10
    for i in range(1,n):
        fi = 9
        for j in range(9,9-i,-1):
            fi *= j
        dp[i] = dp[i-1] + fi
    return dp[-1]
n =3
countNumbersWithUniqueDigits(n)

算法66------計算各個位數不同的數字個數【動態規劃】