最大为 N 的数字组合
题目简介
902. 最大为 N 的数字组合
难度:困难
给定一个按 非递减顺序 排列的数字数组 digits 。你可以用任意次数 digits[i] 来写的数字。例如,如果 digits = [‘1’,’3’,’5’],我们可以写数字,如 ‘13’, ‘551’, 和 ‘1351315’。
返回 可以生成的小于或等于给定整数 n 的正整数的个数 。
示例 1:
1 | 输入:digits = ["1","3","5","7"], n = 100 |
示例 2:
1 | 输入:digits = ["1","4","9"], n = 1000000000 |
示例 3:
1 | 输入:digits = ["7"], n = 8 |
解法
时间与内存情况:
设数字n的长度(严谨的表述应该为将n转化为切片后n的长度)为ln
,切片digits
的长度为ld
。答案设为res
。
此题笔者一开始并没有想到官方解法中的数位动态规划。而是注意到了在到达n的长度之前的情况(如示例2,n
为十位长度的数,则在长度为1
到9
位的情况下)res
只需要简单的加上ld
的1次方
,2次方
,一直到ln-1次方
即可。
而在与n
的长度相等时,则需要比较最高位与digits
中的数字大小:
- 如果
digits
中数字小于
当前最高位,则res
只需加上ld
的当前数字长度减1次方
。 - 如果
digits
中数字大于
当前最高位,则选取这个数字后,后面再加任何数都不符合题意,所以直接忽略掉这种情况即可。 - 如果
digits
中数字等于
当前最高位,那么我们需要判断截掉当前最高位后剩下的数有多少情况满足题意。也就是说,将n去掉最高位后的数
再按照上述流程走一遍。(即递归)
代码如下,因为Go语言中没有针对int
类型的指数内置函数,所以只能自己实现一个(这是个Go非常不友好的地方,开发人员解释的原因是int
类型的此类函数用户可以轻易实现,而float64
类型大部分人实现有难度,所以只提供了float64
类型的。笔者并不赞成此解释)。最后两个函数大家可以略过不看:
1 | func atMostNGivenDigitSet(digits []string, n int) int { |
由于笔者在审题时没有看到数字数组是 非递减顺序 排列,所以没有针对此情况优化。得益于Go强大的效率,此代码执行用时依然是0ms
。读者可以自己尝试优化一下。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Chao Pang的个人主页!