题目描述
思路解析动画文字版
版本号比较的魂就一句话:分段、转数字、逐段比。下面把两个版本号切成段排成一排,一段一段往右走着比给你看。
第一步 · 按 "." 切段:先把 version1 沿着每个 "." 剪开,得到 3 段修订号:"1"、"01"、"3"。注意这里还是字符串,"01" 带着前导 0。
同样切 v2:version2 切出来只有 2 段:"1"、"001"。它比 v1 少一段——这个差异待会儿要靠「缺的段补 0」来处理。
我们用一个指针 i 从 0 走到「两边最长段数」。每一段:v1 这段有就取值、没有按 0 算,v2 同理,然后比这两个数。下面排成一排逐段演示。
对齐成 3 个比较位:把两边对齐成 3 个比较位,每格左边是 v1 的段、右边是 v2 的段。第 2 位 v2 没有,标「缺」(按 0 算)。马上让指针 i 从第 0 位开始一格一格往右比。
比较位 0 · 取数值:看第 0 位:v1 这段 "1" 转成整数是 1,v2 这段 "1" 也是 1。把两个字符串都先变成数字,再比大小。
比较位 0 · 1 == 1 相等:1 == 1,第 0 位打平,染绿表示已比过且相等。还没分出大小,指针 i 往右挪到第 1 位继续。
i 前进 → 1:指针走到第 1 位。这里 v1 是 "01"、v2 是 "001",字符串明显不同。但别急着判不等——版本号要忽略前导 0,得先转成数字。
比较位 1 · 忽略前导 0:关键一步:转整数时,"01" 和 "001" 开头的 0 全被丢掉,都变成 1。格子里也同步刷新成 "1 | 1"。这就是「忽略前导 0」。
比较位 1 · 1 == 1 相等:转成数字后 1 == 1,第 1 位也打平、染绿。可见若按字符串比就会冤判,按数值比才对。指针挪到最后一位第 2 位。
i 前进 → 2:走到第 2 位。v1 有 "3",但 v2 总共才 2 段、到这一位已经没有段了。前面说过——缺的段当 0。
比较位 2 · 缺段补 0:把 v2 缺的这段补成 0,格子刷新成 "3 | 0"。现在两边都有数可比了:v1 是 3,v2 是 0。
比较位 2 · 3 > 0 分出胜负!:3 > 0!终于分出胜负:v1 在这一位更大,说明 v1 整体更新,立刻返回 1。前两位都平、第三位 v1 胜出。
结论:整道题的节奏:从左到右一段一段比,相等就看下一段,一不等立刻定输赢;比到头都相等才返回 0。这就是版本号比较。
再看相等例 · "1.0" vs "1.0.0":换个相等的例子:"1.0" 和 "1.0.0"。v2 多一段,所以共 3 个比较位,v1 第 2 位要补 0。先从第 0 位开始比。
位 0 · 1==1:第 0 位 1 == 1,打平,继续看下一位。
位 1 · 0==0:第 1 位都是 0,0 == 0 平局,再往后。
位 2 · 缺段补 0:第 2 位 v1 缺,补 0;v2 是 "0" 也是 0。格子刷新成 "0 | 0",两边相等。
比到头全平 → 返回 0:三个位全打平,没有任何一位分出胜负,补 0 让多出来的 ".0" 不影响结果。所以 "1.0" 和 "1.0.0" 相等,返回 0。
再看更小例 · "0.1" vs "1.1":最后看一个 v1 更小的例子:"0.1" 和 "1.1"。两边都 2 段,排成 2 个比较位,准备从第 0 位开始。
位 0 · 取数值:指针落在第 0 位。v1 这段 "0" 是 0,v2 这段 "1" 是 1。先把两段都转成数字。
位 0 · 0 < 1 立刻定输赢:第 0 位就 0 ,v1 更小,立刻返回 -1,后面的段根本不用看(灰掉)——高位一旦分出大小,低位再大也翻不了盘。
边界三连:把「前导 0」「尾部补 0」「高位定胜负」三种边界想清楚,代码就稳了。
面试追问:把「为何不能字符串比」「缺段补 0 的语义」「溢出处理」讲清楚,是这题的加分点。
参考代码
class Solution: def compareVersion(self, version1, version2): a = version1.split(".") # 按 . 切段 b = version2.split(".") for i in range(max(len(a), len(b))): x = int(a[i]) if i < len(a) else 0 # 缺段补0,int去前导0 y = int(b[i]) if i < len(b) else 0 if x != y: # 一不等立刻定胜负 return 1 if x > y else -1 return 0 # 比到头全平复杂度
- 时间复杂度:O(n+m),n、m 为两个版本号长度。切段 + 逐字符转数值各扫一遍,线性
- 空间复杂度:O(n+m),split 出来的段数组占用与长度成正比;C++ 边扫边算可做到 O(1)
易错点
面试追问把动画讲成自己的话
追问为什么不能直接按字符串字典序比?
追问段数不同怎么办?为什么补 0 而不是判更长的大?
追问若修订号极大可能溢出怎么办?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
回文子串
LeetCode 647 · 中等 · 沿着 字符串套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题