版本号比较

实现比较两个版本号大小的函数

问题

实现一个函数 compareVersion(v1, v2),比较两个版本号的大小。

  • 返回 1:v1 > v2
  • 返回 -1:v1 < v2
  • 返回 0:v1 = v2

示例:

  • compareVersion('1.2.3', '1.2.4')-1
  • compareVersion('2.0', '1.9.9')1
  • compareVersion('1.0.0', '1')0

解答

function compareVersion(v1, v2) {
  // 按 '.' 分割成数组
  const arr1 = v1.split('.')
  const arr2 = v2.split('.')
  
  // 取最大长度,确保比较完整
  const maxLen = Math.max(arr1.length, arr2.length)
  
  for (let i = 0; i < maxLen; i++) {
    // 缺失的版本段视为 0
    const num1 = parseInt(arr1[i] || '0', 10)
    const num2 = parseInt(arr2[i] || '0', 10)
    
    if (num1 > num2) return 1
    if (num1 < num2) return -1
  }
  
  // 所有段都相等
  return 0
}

测试

console.log(compareVersion('1.2.3', '1.2.4'))   // -1
console.log(compareVersion('2.0', '1.9.9'))     // 1
console.log(compareVersion('1.0.0', '1'))       // 0
console.log(compareVersion('1.10', '1.9'))      // 1
console.log(compareVersion('0.1', '0.0.1'))     // 1

处理前导零的版本

如果版本号可能包含前导零(如 '1.01.1'),parseInt 已经能正确处理:

console.log(compareVersion('1.01', '1.1'))  // 0
console.log(compareVersion('1.001', '1.1')) // 0

不使用 split 的写法

function compareVersion(v1, v2) {
  let i = 0, j = 0
  
  while (i < v1.length || j < v2.length) {
    // 解析 v1 当前段
    let num1 = 0
    while (i < v1.length && v1[i] !== '.') {
      num1 = num1 * 10 + Number(v1[i])
      i++
    }
    i++ // 跳过 '.'
    
    // 解析 v2 当前段
    let num2 = 0
    while (j < v2.length && v2[j] !== '.') {
      num2 = num2 * 10 + Number(v2[j])
      j++
    }
    j++ // 跳过 '.'
    
    if (num1 > num2) return 1
    if (num1 < num2) return -1
  }
  
  return 0
}

关键点

  • . 分割后逐段比较,转为数字避免字符串比较的坑('10' < '9'
  • 长度不同时,缺失的段视为 0'1.0' 等于 '1.0.0'
  • parseInt 自动处理前导零('01'1
  • 双指针写法可以避免创建数组,空间复杂度更低