LeetCode 165:版本号比较算法深度解析(compareVersion)
2026-06-19
NEW个对象
📌 LeetCode 165:版本号比较算法深度解析(compareVersion)
在系统开发与面试中,“版本号比较”是一个非常经典的问题。它不仅考察字符串处理能力,还涉及整数解析、边界补齐、逐段比较等基础算法思想。
本文将围绕 Java/Python 思维中的核心实现逻辑进行拆解,帮助你从“会做题”升级到“理解本质”。
🎯 一、问题本质拆解
版本号通常形如:1.0.3 / 2.1 / 3.0.0.1
它的比较规则并不是字符串字典序,而是“逐段整数比较”。
👉 核心规则如下:
它的比较规则并不是字符串字典序,而是“逐段整数比较”。
👉 核心规则如下:
- 按 “.” 分割版本号
- 每一段按整数比较,而不是字符串
- 缺失的部分默认补 0
- 从左到右逐段比较
⚠️ 注意:不能直接用字符串比较,比如 "1.10" 和 "1.2",字符串比较会误判大小关系。
🚀 二、算法核心思想
本题的核心可以抽象为三个步骤:
👉 本质是一种“多段整数数组比较问题”。
- 字符串拆分(split)
- 类型转换(str → int)
- 逐段比较(compare loop)
👉 本质是一种“多段整数数组比较问题”。
📌 三、标准实现代码解析
class Solution:
# 定义比较版本号的方法(self 用于类实例调用)
def compareVersion(self, version1: str, version2: str) -> int:
# 1️⃣ 按 "." 拆分版本号并转为整数数组
# 1️⃣ map(函数,可迭代集合),类似javamap转换
v1 = list(map(int, version1.split(".")))
v2 = list(map(int, version2.split(".")))
# 2️⃣ 获取最大长度,用于对齐比较
max_len = max(len(v1), len(v2))
# 3️⃣ 补 0 保证长度一致
v1.extend([0] * (max_len - len(v1)))
v2.extend([0] * (max_len - len(v2)))
# 4️⃣ 逐段比较
for i in range(max_len):
if v1[i] > v2[i]:
return 1
elif v1[i] < v2[i]:
return -1
# 5️⃣ 完全相等
return 0
```
# 定义比较版本号的方法(self 用于类实例调用)
def compareVersion(self, version1: str, version2: str) -> int:
# 1️⃣ 按 "." 拆分版本号并转为整数数组
# 1️⃣ map(函数,可迭代集合),类似javamap转换
v1 = list(map(int, version1.split(".")))
v2 = list(map(int, version2.split(".")))
# 2️⃣ 获取最大长度,用于对齐比较
max_len = max(len(v1), len(v2))
# 3️⃣ 补 0 保证长度一致
v1.extend([0] * (max_len - len(v1)))
v2.extend([0] * (max_len - len(v2)))
# 4️⃣ 逐段比较
for i in range(max_len):
if v1[i] > v2[i]:
return 1
elif v1[i] < v2[i]:
return -1
# 5️⃣ 完全相等
return 0
```
🔥 四、执行流程拆解(一步一步理解)
我们用例子:
version1 = 1.2.10
version2 = 1.2.3
👉 第一步拆分:
version1 = 1.2.10
version2 = 1.2.3
👉 第一步拆分:
- v1 = [1, 2, 10]
- v2 = [1, 2, 3]
- 1 == 1 → 继续
- 2 == 2 → 继续
- 10 > 3 → 返回 1
⚠️ 五、常见错误与坑点
❌ 错误1:直接字符串比较
❌ 错误2:忽略 1.0 = 1.0.0
❌ 错误3:未补 0 导致长度不一致
❌ 错误4:把版本当 float(会丢失精度)
❌ 错误2:忽略 1.0 = 1.0.0
❌ 错误3:未补 0 导致长度不一致
❌ 错误4:把版本当 float(会丢失精度)
💡 正确思路始终是:拆段 + 转整数 + 对齐 + 比较
🚀 六、复杂度分析
时间复杂度:O(n + m)
空间复杂度:O(n + m)
👉 n 和 m 分别表示版本号的段数。
✔ 性能已经足够优秀,可用于生产逻辑(如版本控制系统)。
空间复杂度:O(n + m)
👉 n 和 m 分别表示版本号的段数。
✔ 性能已经足够优秀,可用于生产逻辑(如版本控制系统)。
🎯 七、面试进阶优化思路
上述解法已经很好,但在面试中,面试官可能会继续追问:
👉 能否不使用 split?
👉 能否 O(1) 空间?
于是就引出“双指针解析法”:
👉 能否不使用 split?
👉 能否 O(1) 空间?
于是就引出“双指针解析法”:
class Solution:
def compareVersion(self, version1: str, version2: str) -> int:
i = j = 0
n, m = len(version1), len(version2)
while i < n or j < m:
num1 = num2 = 0
while i < n and version1[i] != '.':
num1 = num1 * 10 + (ord(version1[i]) - 48)
i += 1
i += 1
while j < m and version2[j] != '.':
num2 = num2 * 10 + (ord(version2[j]) - 48)
j += 1
j += 1
if num1 > num2:
return 1
elif num1 < num2:
return -1
return 0
```
def compareVersion(self, version1: str, version2: str) -> int:
i = j = 0
n, m = len(version1), len(version2)
while i < n or j < m:
num1 = num2 = 0
while i < n and version1[i] != '.':
num1 = num1 * 10 + (ord(version1[i]) - 48)
i += 1
i += 1
while j < m and version2[j] != '.':
num2 = num2 * 10 + (ord(version2[j]) - 48)
j += 1
j += 1
if num1 > num2:
return 1
elif num1 < num2:
return -1
return 0
```
💡 八、两种解法对比总结
| 方式 | 空间复杂度 | 可读性 | 面试评分 |
|---|---|---|---|
| split补0法 | O(n) | 高 | ⭐⭐⭐ |
| 双指针解析 | O(1) | 中 | ⭐⭐⭐⭐⭐ |
🎯 九、总结提升
✔ 本题本质是“多段整数比较”
✔ split 解法适合快速实现
✔ 双指针解法适合面试加分
✔ 核心思想是“逐段解析 + 逐段比较”
💡 一句话总结:
版本号比较不是字符串问题,而是“结构化整数比较问题”。
✔ split 解法适合快速实现
✔ 双指针解法适合面试加分
✔ 核心思想是“逐段解析 + 逐段比较”
💡 一句话总结:
版本号比较不是字符串问题,而是“结构化整数比较问题”。
相关文章
-
Docker部署Spring Boot项目
1、首先是将项目打成jar包 2、将jar包上传到服务器上 3、在jar的文件目录下,编写Dockerfile和publish.sh 4、运行publish.sh
NEW个对象 2024-10-08
-
程序员面试技术面和HR面试,最后要问什么问题?
程序员面试技术面和HR面试,最后要问什么问题?
NEW个对象 2026-06-14
-
MyBatis BaseExecutor 模板方法模式与策略模式详解
MyBatis BaseExecutor 模板方法模式与策略模式详解
NEW个对象 2026-06-14
NEW个对象
JAVA是世界上最好的语言