每日一题:LeetCode 165:比较版本号

一、题目要求

给你两个版本号字符串:

复制代码
version1
version2

例如:

复制代码
version1 = "1.2"
version2 = "1.10"

版本号由 . 分隔成多个"修订号"。

例如:

复制代码
"1.2"
→ [1, 2]

"1.10"
→ [1, 10]

比较时,要从左到右逐段比较。

如果某一段更大,就能直接判断哪个版本更大。


二、为什么不能直接比较字符串?

比如:

复制代码
"1.2" > "1.10"

不能用这种方式直接判断版本号大小。

因为字符串比较是按字符比较,不是按数值比较。

我们真正想比较的是:

复制代码
1 和 1
2 和 10

所以应该先拆分:

复制代码
"1.2".split(".")

得到:

复制代码
["1", "2"]

而:

复制代码
"1.10".split(".")

得到:

复制代码
["1", "10"]

然后逐段转成数字比较。


三、完整 JavaScript 代码

javascript 复制代码
var compareVersion = function(version1, version2) {
  const v1 = version1.split(".")
  const v2 = version2.split(".")

  const len = Math.max(v1.length, v2.length)

  for (let i = 0; i < len; i++) {
    const n1 = Number(v1[i] || 0)
    const n2 = Number(v2[i] || 0)

    if (n1 > n2) return 1
    if (n1 < n2) return -1
  }

  return 0
}

四、第一步:split 拆版本号

代码:

复制代码
const v1 = version1.split(".")
const v2 = version2.split(".")

例如:

复制代码
version1 = "1.2.3"

执行:

复制代码
version1.split(".")

得到:

复制代码
["1", "2", "3"]

所以 split(".") 的作用就是:

按照 . 把字符串拆成数组。


五、为什么要取最大长度?

代码:

复制代码
const len = Math.max(v1.length, v2.length)

因为两个版本号的段数可能不同。

比如:

复制代码
version1 = "1.0"
version2 = "1.0.0.0"

拆开后:

复制代码
v1 = ["1", "0"]

v2 = ["1", "0", "0", "0"]

如果只遍历较短数组,就比较不完整。

所以要取:

复制代码
Math.max(v1.length, v2.length)

也就是:

两个数组中更长的那个长度。


六、缺失的版本号为什么当 0?

题目规定:

如果某个版本号缺少某一段,就把它看成 0。

比如:

复制代码
1.0
1.0.0

实际上应该看成:

复制代码
1.0.0
1.0.0

所以这两个版本相等。

代码里用了:

复制代码
v1[i] || 0

意思是:

如果:

复制代码
v1[i]

不存在,就使用:

复制代码
0

例如:

复制代码
const v1 = ["1", "0"]

当:

复制代码
i = 2

时:

复制代码
v1[2]
// undefined

于是:

复制代码
v1[2] || 0

结果就是:

复制代码
0

七、为什么要用 Number()?

代码:

复制代码
const n1 = Number(v1[i] || 0)
const n2 = Number(v2[i] || 0)

因为 split() 得到的还是字符串。

例如:

复制代码
"1.10".split(".")

得到:

复制代码
["1", "10"]

其中:

复制代码
"10"

还是字符串。

所以我们要:

复制代码
Number("10")

得到:

复制代码
10

这样才能进行真正的数值比较。


八、前导 0 怎么处理?

例如:

复制代码
version1 = "1.01"
version2 = "1.001"

题目要求忽略前导 0。

所以:

复制代码
01
001

都应该看成:

复制代码
1

这也是为什么用:

复制代码
Number()

很方便。

例如:

复制代码
Number("01")
// 1

Number("001")
// 1

所以前导 0 会自动被去掉。


九、逐段比较

核心代码:

复制代码
if (n1 > n2) return 1
if (n1 < n2) return -1

意思是:

如果当前这一段已经能分出大小,就直接返回。

比如:

复制代码
version1 = "1.2"
version2 = "1.10"

第一轮:

复制代码
1 和 1

相等,继续。

第二轮:

复制代码
2 和 10

因为:

复制代码
2 < 10

所以:

复制代码
return -1

后面不需要再比较了。


十、为什么最后 return 0?

如果整个循环都没有返回:

复制代码
1

或者:

复制代码
-1

说明所有对应版本号都相等。

例如:

复制代码
version1 = "1.0"
version2 = "1.0.0"

比较过程:

复制代码
1 == 1
0 == 0
0 == 0

所以最终:

复制代码
return 0

表示:

两个版本号相同。


十一、完整执行示例

例如:

复制代码
version1 = "1.2"
version2 = "1.10"

拆分:

复制代码
v1 = ["1", "2"]
v2 = ["1", "10"]

最大长度:

复制代码
len = 2

第一轮:

复制代码
n1 = 1
n2 = 1

相等,继续。

第二轮:

复制代码
n1 = 2
n2 = 10

因为:

复制代码
2 < 10

所以:

复制代码
return -1

十二、再看长度不同的情况

复制代码
version1 = "1.0"
version2 = "1.0.0"

拆分:

复制代码
v1 = ["1", "0"]

v2 = ["1", "0", "0"]

第三轮时:

复制代码
v1[2]
// undefined

所以:

复制代码
Number(v1[2] || 0)
// 0

而:

复制代码
Number(v2[2] || 0)
// 0

两边还是一样。

最终:

复制代码
return 0

十三、这道题的核心思路

这道题其实可以压缩成四步:

复制代码
1. 用 split(".") 拆版本号

2. 遍历两个数组的最大长度

3. 每一段用 Number() 转成数字

4. 从左到右逐段比较

只要某一段出现:

复制代码
n1 > n2

就返回:

复制代码
1

如果:

复制代码
n1 < n2

就返回:

复制代码
-1

全部一样:

复制代码
0

十四、这道题主要考什么?

主要考三个点。

1. 字符串处理

复制代码
split(".")

把版本号拆开。

2. 边界处理

版本长度不一样时:

复制代码
v1[i] || 0

缺失部分按 0 处理。

3. 类型转换

复制代码
Number()

把字符串版本号转换成数字,并自动处理前导 0。


总结

最终代码:

复制代码
var compareVersion = function(version1, version2) {
  const v1 = version1.split(".")
  const v2 = version2.split(".")

  const len = Math.max(v1.length, v2.length)

  for (let i = 0; i < len; i++) {
    const n1 = Number(v1[i] || 0)
    const n2 = Number(v2[i] || 0)

    if (n1 > n2) return 1
    if (n1 < n2) return -1
  }

  return 0
}

总结:

先 split 拆版本号,再从左到右逐段转成数字比较;缺失部分补 0,前导 0 用 Number 自动处理。

相关推荐
道尔柯南1 小时前
C++ 面向对象编程入门:类和对象(上)
开发语言·c++·算法
Navigator_Z1 小时前
LeetCode //C - 1288. Remove Covered Intervals
c语言·算法·leetcode
码爸2 小时前
决策树介绍与示例
python·算法·机器学习
动词ing2 小时前
【题目练习】字符串相乘
算法
0+1112 小时前
算法 --链表
数据结构·算法·leetcode·链表
圣保罗的大教堂2 小时前
leetcode 2333. 最小差值平方和 中等
leetcode
aqiu1111113 小时前
【C++算法打怪专栏】C++ `unordered_set` 常用初始化与插入方法总结
开发语言·c++·算法
Terra.K3 小时前
高精度阶乘求和模板深度解析
开发语言·c++·算法
Peregrine94 小时前
C++ - > 类和对象
java·c++·算法