We have a sorted set of digits `D`, a non-empty subset of `{'1','2','3','4','5','6','7','8','9'}`. (Note that `'0'` is not included.)
Now, we write numbers using these digits, using each digit as many times as we want. For example, if D = {'1','3','5'}
, we may write numbers such as '13', '551', '1351315'
.
Return the number of positive integers that can be written (using the digits of D
) that are less than or equal to N
.
Example 1:
Input: D = ["1","3","5","7"], N = 100
Output: 20
Explanation:
The 20 numbers that can be written are:
1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77.
Example 2:
Input: D = ["1","4","9"], N = 1000000000
Output: 29523
Explanation:
We can write 3 one digit numbers, 9 two digit numbers, 27 three digit numbers,
81 four digit numbers, 243 five digit numbers, 729 six digit numbers,
2187 seven digit numbers, 6561 eight digit numbers, and 19683 nine digit numbers.
In total, this is 29523 integers that can be written using the digits of D.
Note:
D
is a subset of digits'1'-'9'
in sorted order.1 <= N <= 10^9
這道題給了我們一個有序字符串數組,里面是0到9之間的數(這里博主就納悶了,既然只有一位數字,為啥不用 char 型,而要用 string 型),然后又給了一個整型數字N,問無限制次數使用D中的任意個數字,能組成多個不同的小於等於D的數字。先來分析例子1,當N為 100 時,所有的一位數和兩位數都是可以的,既然可以重復使用數字,假設總共有n個數字,那么對於兩位數來說,十位上和個位上分別都有n種可能,總共就是 n^2 種可能,對於一位數來說,總共n種可能。那么看到這里就可以歸納出當N總共有 len 位的話,我們就可以快速的求出不超過 len-1 位的所有情況綜合,用個 for 循環,累加n的指數即可。然后就要來分析和數字N位數相等的組合,題目中的兩個的例子的N都是1開始的,實際上N可以是任何數字,舉個例子來說吧,假如 D={"1","3","5","7"},N=365,那么根據前面的分析,我們可以很快的算出所有的兩位數和一位數的組合情況總數 4 + 4^2 = 20 個。現在要來分析三位數都有哪些組合,由於D數組是有序的,所以我們從開頭遍歷的話先取到的就是最小的,這時候有三種情況,小於,等於,和大於,每種的處理情況都有些許不同,這里就拿上面提到的例子進行一步一步的分析:
- 對於N的百位數字3來說,D中的1小於N中的百位上的3,那么此時百位上固定為1,十位和個位上就可以是任意值了,即 1xx,共有 4^2 = 16 個。
- 對於N的百位數字3來說,D中的3等於N中的百位上的3,那么此時百位上固定為3,十位和個位的值還是不確定,此時就不能再繼續遍歷D中的數字了,因為之后的數字肯定大於3,但是我們可以繼續嘗試N的下一位。
- 對於N的十位數字6來說,D中的1小於N中的十位上的6,那么百位和十位分別固定為3和1,個位上就可以是任意值了,即 31x,共有 4 個。
- 對於N的十位數字6來說,D中的3小於N中的十位上的6,那么百位和十位分別固定為3和3,個位上就可以是任意值了,即 33x,共有 4 個。
- 對於N的十位數字6來說,D中的5小於N中的十位上的6,那么百位和十位分別固定為3和5,個位上就可以是任意值了,即 35x,共有 4 個。
- 對於N的十位數字6來說,D中的7大於N中的十位上的6,此時再也組不成小於N的數字了,直接返回最終的 20+16+4+4+4=48 個。
代碼如下:
class Solution {
public:
int atMostNGivenDigitSet(vector<string>& D, int N) {
string str = to_string(N);
int res = 0, n = D.size(), len = str.size();
for (int i = 1; i < len; ++i) res += pow(n, i);
for (int i = 0; i < len; ++i) {
bool hasSameNum = false;
for (string &d : D) {
if (d[0] < str[i]) res += pow(n, len - 1 - i);
else if (d[0] == str[i]) hasSameNum = true;
}
if (!hasSameNum) return res;
}
return res + 1;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/902
參考資料:
https://leetcode.com/problems/numbers-at-most-n-given-digit-set/
https://leetcode.com/problems/numbers-at-most-n-given-digit-set/discuss/225123/c%2B%2B100
[LeetCode All in One 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)