我想创建一个string
,其中包含*
个符号n
次。
我只是这样看:
val s = ""
val n = 100
for (j in 0 until n) {
s += "*"
}
但它看起来很丑,而且时间复杂度为O(n ^ 2)。 Kotlin有没有办法在没有时间复杂度更高的循环的情况下做到这一点?
答案 0 :(得分:10)
内置CharSequence.repeat
扩展程序以有效的方式执行此操作,请参阅来源here。
val str: String = "*".repeat(100)
当然,这仍然需要O(n)步骤来创建字符串。但是,使用这种内置的stdlib功能有其优点:它具有跨平台,易于阅读,并且如果有更高效的解决方案,可以随着时间的推移提高性能。无论如何,它内部的循环可能会被编译器或运行时优化。
答案 1 :(得分:2)
StringBuilder
会改善memory footprint here:
val sb = StringBuilder()
val n = 100
for (j in 0 until n) {
sb.append("*")
}
答案 2 :(得分:1)
感谢Anton Sizikov和https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/repeat.html,我们可以写:
val sb = StringBuilder().apply{
repeat(100) {
append("*")
}
}
但这是一种简单的方法。看一个power函数。具有O(log n)复杂度。
对于StringBuilder
:
private fun power(sb: StringBuilder, n: Int): StringBuilder =
when {
n == 0 -> StringBuilder("")
n % 2 == 0 -> {
val part = power(sb, n / 2)
part.append(part)
}
else -> {
val part = power(sb, n / 2)
part.append(part).append(sb)
}
}
对于String
:
private fun pow(s: String, n: Int): String =
when {
n == 0 -> ""
n % 2 == 0 -> pow(s, n / 2).repeat(2)
else -> s + pow(s, n / 2).repeat(2)
}
然后我们可以调用它们:
// 1.
val sb1 = StringBuilder().apply {
repeat(100) {
append("*")
}
}
// 2.
val sb2 = power(StringBuilder("*"), 100)
// 3.
val s = power("*", 100)
println(sb1.toString())
println(s)
println(sb2.toString())
答案 3 :(得分:0)
CharSequence.repeat的替代方案是具有init函数的CharArray:
git apply -3
此解决方案的优点是您可以定义前缀,后缀和分隔符。
答案 4 :(得分:0)
您可以重载*
运算符以将其映射到现有的repeat extension:
public operator fun CharSequence.times(count: Int): String {
return repeat(count)
}
fun main() {
val s = "*" * 101
println(s)
println("Badger " * 12 + "Mushroom " * 2)
println(s)
}
答案 5 :(得分:0)
如果您需要分隔符,列表中的此初始化函数很有帮助:
val str: String = List(100) { "*" }.joinToString(",")