朱涛 · Kotlin 编程第一课
朱涛
Google 认证的 Kotlin、Android 开发者专家,博客“Kotlin Jetpack 实战”作者
6717 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 50 讲
朱涛 · Kotlin 编程第一课
15
15
1.0x
00:00/00:00
登录|注册

春节刷题计划(二)| 一题三解,搞定版本号判断

你好,我是朱涛。今天是除夕夜,先祝你虎年春节快乐!
在上节刷题课中,我给你留了一个作业,那就是:用 Kotlin 来完成 LeetCode 的 165 号题《版本号判断》。那么今天这节课,我就来讲讲我的解题思路,希望能给你带来一些启发。
这道题目其实跟我们平时的工作息息相关。给你两个字符串代表的版本号,需要你判断哪个版本号是新的,哪个版本号是旧的。比如,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 上面给了我们一个待实现的方法,大致如下:
fun compareVersion(version1: String, version2: String): Int {
// 待完善
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了使用Kotlin解决版本号判断问题的三种思路。第一种思路是使用split函数和转换成整数进行对比,第二种思路是通过模拟split的过程进行比对工作,第三种思路是使用扩展函数进行优化。作者展示了Kotlin的应用和不同解题思路的实现,同时指出了各种思路的优劣。第一种思路逻辑清晰,代码量小,但时间复杂度、空间复杂度较差;第二种思路逻辑复杂,代码量稍大,但时间复杂度、空间复杂度非常好;第三种思路代码逻辑清晰,但代码量大,时间复杂度、空间复杂度较差。此外,第三种思路还有一个额外的优势,即自己实现的扩展函数可以用于解决其他问题。读者可以从中学习到Kotlin的具体应用和算法解题的思路。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《朱涛 · 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-31
    6
  • 梁中华
    这样写也算比较简洁把: 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-19
    2
  • 白乾涛
    工作中谁敢用方法三,我保准让他默写十遍!

    作者回复: 哈哈哈~仅用于学习用途。

    2022-03-02
    2
  • 白乾涛
    解法二稍加封装了一下 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_Adr
    class 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
  • PP
    fun 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归属地:福建
收起评论
显示
设置
留言
8
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部