春节刷题计划(二)| 一题三解,搞定版本号判断
朱涛
你好,我是朱涛。今天是除夕夜,先祝你虎年春节快乐!
这道题目其实跟我们平时的工作息息相关。给你两个字符串代表的版本号,需要你判断哪个版本号是新的,哪个版本号是旧的。比如,2.0 与 1.0 对比的话,2.0 肯定是新版本,1.0 肯定是旧版本。对吧?
不过,这里面还有一些问题需要留意,这些都是我们在正式写代码之前要弄清楚的。
首先,版本号是可能以 0 开头的。比如 0.1、1.01,这些都是合理的版本号。
另外,如果是以 0 开头的话,1 个 0 和多个 0,它们是等价的,比如 1.01、1.001、1.00001 之间就是等价的,也就是说这几个版本号其实是相等的。
还有,1.0、1.0.0、1.0.0.0 它们之间也是等价的,也就是说这几个版本号也是相等的。
思路一
好了,理解了题意以后,我们就可以开始写代码了,LeetCode 上面给了我们一个待实现的方法,大致如下:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了使用Kotlin解决版本号判断问题的三种思路。第一种思路是使用split函数和转换成整数进行对比,第二种思路是通过模拟split的过程进行比对工作,第三种思路是使用扩展函数进行优化。作者展示了Kotlin的应用和不同解题思路的实现,同时指出了各种思路的优劣。第一种思路逻辑清晰,代码量小,但时间复杂度、空间复杂度较差;第二种思路逻辑复杂,代码量稍大,但时间复杂度、空间复杂度非常好;第三种思路代码逻辑清晰,但代码量大,时间复杂度、空间复杂度较差。此外,第三种思路还有一个额外的优势,即自己实现的扩展函数可以用于解决其他问题。读者可以从中学习到Kotlin的具体应用和算法解题的思路。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《朱涛 · Kotlin 编程第一课》,新⼈⾸单¥59
《朱涛 · Kotlin 编程第一课》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(8)
- 最新
- 精选
- qinsi方法三有点一言难尽吧... 尝试写一个python的版本: ```python class Solution: def compareVersion(self, ver1: str, ver2: str) -> int: to_nums = lambda ver: map(int, ver.split('.')) zipped = zip_longest(*map(to_nums, [ver1, ver2]), fillvalue=0) cmp = lambda a, b: (a > b) - (a < b) return next((i for i in starmap(cmp, zipped) if i != 0), 0) # return next(filter(lambda x: x != 0, starmap(cmp, zipped)), 0) ``` 文中的zipLongest实现接受Iterable<String>,返回List<Pair<Int, Int>>。这意味: 1. 输入是Iterable,输出成了List。这样就不适用于输入长度无限的情况,或是可以惰性求值的情况。在本题中,因为只要遇到第一个不相同的子版本号就可以返回,所以可以不用生成完整的List,正好是可以利用惰性求值的情况; 2. 输入Iterable的基类型是String,输出Pair的基类型是Int,这就把类型转换写死在了实现里,让实现失去了通用性,即便沉淀出来可能用途也有限吧; 3. 文中的实现只支持一个Iterable与另一个Iterable进行zip,而python的实现支持任意多个。 这里不是要抬杠,只是想说各种语言的不同特性会形成不同的惯用法,强行使用另一种语言的惯用法可能会显得不伦不类。如有冒犯还请见谅。
作者回复: 嗯,完全理解你的意思。解法三,我写出来的目的也是想让大家看到Kotlin也有不擅长的领域,也是为了展示它丑陋的一面。
2022-01-316 - 梁中华这样写也算比较简洁把: val list1 = version1.split(".") val list2 = version2.split(".") val result = list1.zip(list2) { v1, v2 -> Pair(v1.toInt(), v2.toInt()) } .onEach { if (it.first != it.second) { return it.first.compareTo(it.second) } }.run { return list1.size - list2.size }
作者回复: 很不错,毕竟标准库里就有zip,省事。
2022-03-192 - 白乾涛工作中谁敢用方法三,我保准让他默写十遍!
作者回复: 哈哈哈~仅用于学习用途。
2022-03-022 - 白乾涛解法二稍加封装了一下 fun compareVersion(version1: String, version2: String): Int { val v1 = Version(0, 0, version1) val v2 = Version(0, 0, version2) while (v1.index < version1.length || v2.index < version2.length) { v1.dealVersion() v2.dealVersion() if (v1.subValue != v2.subValue) { return v1.subValue.compareTo(v2.subValue) } } return 0 } data class Version(var index: Int, var subValue: Int, var text: String) { fun dealVersion(): Version { subValue = 0 while (index < text.length && text[index] != '.') { subValue = subValue * 10 + text[index].toInt() - '0'.toInt() index++ } index++ return this } }
作者回复: 这思路不错。
2022-03-02 - Geek_Adrclass Solution { // ax+b // symbol 和 tmp 都是处理表达式临时变量 data class Expr(var a: Int, var b: Int, var symbol: Int, var tmp: String) fun solveEquation(equation: String): String { return equation .split("=")// 1、分成前后两个部分 .map {// 2、处理表达式为 ax+b "$it+"//骚操作加"+":防止表达式最后一点丢失处理 .fold(Expr(0, 0, 1, "")) { acc, c -> when (c) { '+', '-' -> { if (acc.tmp.contains("x")) { acc.a += acc.symbol * acc.tmp.replace("x", "").ifBlank { "1" }.toInt() } else { acc.b += acc.symbol * acc.tmp.ifBlank { "0" }.toInt() } acc.symbol = if (c == '+') 1 else -1 acc.tmp = "" } else -> { acc.tmp += c } } acc } }.reduce { acc, expr -> // 3、前段 减 后段 acc.a -= expr.a acc.b -= expr.b acc }.run { when { a == 0 && b != 0 -> "No solution" a == 0 -> "Infinite solutions" else -> "x=${-1 * b / a}" } } } }
作者回复: 这个思路有点意思,大家可以来看看。
2022-02-19 - 苹果是我咬的class Solution { fun solveEquation(equation: String): String { val eq = equation.replace("-", "+-").split("=") val (lx, ln) = parse(eq[0]) val (rx, rn) = parse(eq[1]) val x = lx - rx val n = rn - ln return if (x == 0 && n != 0) { "No solution" } else if (x == 0 && n == 0) { "Infinite solutions" } else { "x=${ n / x }" } } fun parse(eq: String): Pair<Int, Int> { val exp = eq.split("+") var (x, n) = 0 to 0 exp.filter { !it.contains("x") && it != "" } .forEach { n += it.toInt() } exp.filter { it.contains("x") } .forEach { x += if (it.length == 1 || it.length == 2 && it[0] == '-') it.replace("x", "1").toInt() else it.replace("x", "").toInt() } return x to n } }
作者回复: 代码写的不错,条理清晰,最后的if判断可以考虑换成when哈。
2022-02-17 - 郑峰```Kotlin fun solveEquation(equation: String): String { val (left, right) = equation.split("=").take(2) val (lx, ln) = parse(left) val (rx, rn) = parse(right) if (lx == rx) return if (ln == rn) "Infinite solutions" else "No solution" if ((rn - ln) % (lx - rx) != 0) return "No solution" return "x=" + (rn - ln) / (lx - rx) } @OptIn(ExperimentalStdlibApi::class) fun parse(exp: String): Pair<Int, Int> { // Split operands and operators val operands = exp.split("[+-]".toRegex()) val operators = buildList<Int> { add(1) // Add leading + to align with operands addAll(exp.filter { it == '+' || it == '-' }.map { if (it == '+') 1 else -1 }) } var (x, n) = 0 to 0 // Calculate x and n for (i in operands.indices) { if (operands[i].isEmpty()) continue if (operands[i].last() == 'x') { x += operators[i] * (operands[i].dropLast(1).toIntOrNull() ?: 1) } else { n += operators[i] * operands[i].toInt() } } return x to n } ```
作者回复: 不错,思路清晰,集合操作符用的很灵活,注释也恰到好处。return部分的if逻辑可以考虑用when来替代。
2022-02-01 - PPfun solveEquation(equation: String) { var sumX = 0 var numEq = 0 equation.replace("-", "+-").split('=').forEachIndexed { index, s -> s.split('+').forEach { if (it.contains('x')) { val count = if (it == "x") 1 else it.removeSuffix("x").toInt() sumX += if (index == 0) count else -count } else { numEq += if (index == 0) -it.toInt() else it.toInt() } } } println(when { sumX == 0 -> "Infinite solutions" numEq.mod(sumX) == 0 -> "x = ${numEq.div(sumX)}" else -> "no solution" }) }2023-07-27归属地:福建
收起评论