我们有一组排序的数字 D,它是 {‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’} 的非空子集。(请注意,‘0’ 不包括在内。)
现在,我们用这些数字进行组合写数字,想用多少次就用多少次。例如 D = {‘1’,‘3’,‘5’},我们可以写出像 ‘13’, ‘551’, ‘1351315’ 这样的数字。
返回可以用 D 中的数字写出的小于或等于 N 的正整数的数目。
示例 1:
输入:D = [“1”,“3”,“5”,“7”], N = 100
输出:20
解释:
可写出的 20 个数字是:
1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/numbers-at-most-n-given-digit-set
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
dfs 首先统计出1—LEN(n)-1位的数目,因为每个数字可以用任意次,所有每位的数目就是D.length^i(位数),在对len(n)位进行搜索,位数可能非常大,因此要加上记忆化. 当高位小于n的高位时,低位就不需要再判断大小了,这里用flag表示
class Solution {
public int atMostNGivenDigitSet(String[] digits, int n) {
int sum=0;
char []ar=String.valueOf(n).toCharArray();
for(int i=1;i<ar.length;i++)//i表示几位数字
{
sum+=(int)Math.pow(digits.length,i);;
}
//搜索 len[ar]位的数字
memo=new int[2][ar.length+1];
Arrays.fill(memo[0],-1);
Arrays.fill(memo[1],-1);
sum+=dfs(0,0,digits,ar);
return sum;
}
int [][]memo;
//falg==1->上一个高位大于n的上个高位
int dfs(int n,int falg,String[]digits,char []ar)
{
if(memo[falg][n]!=-1)
return memo[falg][n];
if(n==ar.length)
{
return memo[falg][n]=1;
}
int num=0;
for(int i=0;i<digits.length;i++)
{
char c=digits[i].charAt(0);
if(falg==1 || c<=ar[n])
{
num+=dfs(n+1,falg==0&&c==ar[n]?0:1,digits,ar);
}
}
return memo[falg][n]=num;
}
}