1. 程式人生 > >Leetcode:357.計算各個位數不同數字的個數

Leetcode:357.計算各個位數不同數字的個數

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

示例:

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

解題思路:

排列組合問題。題目分析可知,n也就是數字的位數。首先分析一個n位數中不同數字的個數val[n]。

  1. 除了n=1之外,首位數字不可能為0,否則該數實質上是一個n-1位數。如果n=1,直接返回10即可。n=0,直接返回1。
  2. 當n>10時,必然有重複數字,因為阿拉伯數字也就10個。
  3. val[n]=9*(9)*(9-1)*(9-2)*...*(9-(n-2))。高中排列組合的知識。
  4. 沒有必要對每一個val[n]都計算這個連乘式子,因為存在遞推關係va[n]=val[n-1]*(9-(n-2)),演算法可以優化到只算O(n)個乘法運算。
  5. 最後掃描一趟,無需額外空間,即可算出前n個數的和,即為本題所需答案。

C++程式碼
class Solution {
public:
    int countNumbersWithUniqueDigits(int n) {
        if (n == 0) return 1;
        if (n > 10) return countNumbersWithUniqueDigits(10);
        vector<int> dp(n + 1, 1);
        dp[1] = 10;
        if (n == 1) return dp[1];
        int temp = 9, sgn = 9,i;
        for (i = 2; i <= n; i++) {
            dp[i] = temp*sgn;
            temp = dp[i];
            sgn--;
        }
        for (i = 2; i <= n; i++) {
            dp[i] += dp[i - 1];
        }
        return dp.back();
    }
};