我尝试用下一个基本思想来解决leetcode problem:
fun coinChange(coins: IntArray, amount: Int): Int {
fun calc(source: Long, lvl: Int): Int =
if (source == amount.toLong())
lvl
else if (source > amount)
-1
else
coins
.map { calc(source = source + it, lvl = lvl + 1) }
.filter { it > 0 }
.sorted()
.firstOrNull() ?: -1
return calc(source = 0, lvl = 0)
}
这个算法看起来是正确的,但是它非常慢,并且因为堆栈溢出而没有通过测试。在这种情况下,我试着稍微加快它的速度,但是现在它不能正常工作了:
fun coinChange(coins: IntArray, amount: Int): Int {
val memoized = mutableMapOf<Int, Int>()
fun calc(source: Int, lvl: Int): Int =
if (source == amount)
lvl
else if (source > amount)
-1
else
memoized.getOrElse(source) {
val evaluated = coins
.reversed()
.map { calc(source = source + it, lvl = lvl + 1) }
.filter { it > 0 }
.minOrNull() ?: -1
memoized[source] = evaluated
evaluated
}
return calc(source = 0, lvl = 0)
}
对于输入coinChange(coins = intArrayOf(186, 419, 83, 408), amount = 6249)
,它返回36
,但必须是20
。您能帮助我吗?
1条答案
按热度按时间ctehm74n1#
Kotlin(Scala和Swift也是)函数式编程方面被高估了。在你的代码中:反向,Map和过滤触发3个循环。所以最好只做常规的for/while循环。每个调用触发3个循环(虽然它可以通过一个循环完成),你将会有一个很大的性能打击。我已经研究了Kotlin的记忆机制,我没有找到一个适合递归函数。(我希望被指出/教育)(这个https://stackoverflow.com/a/35309775和类似的类方法不起作用。我必须手动管理该高速缓存)好了,我的抱怨已经够多了,这里是手动管理缓存通过189 / 189测试的解决方案
这是未请求的python代码。缓存是用一个简单的decorator @cache很好地完成的
下面是另一种使用手动记忆的递归方法
和Python计数器部分
好吧,你可能仍然不满足于这些解决方案,毕竟,你想使用花哨的函数式编程听起来的东西。好吧,这是使用map的Kotlin代码,我有意识地避免了filter,因为它将需要另一个循环。
由于提交了更多Python解决方案,因此对Python的leetcode测试更加严格,Python等效项无法通过TLE,但您可以在此处看到在Python列表理解中组合的map、filter、min all的一行代码