Article / 文章

LeetCode 第165题:比较版本号

给你两个版本号 version1 和 version2,请你比较它们。 版本号由一个或多个修订号组成,各修订号由一个 '.' 连接。每个修订号由 多位数字 组成,可能包含 前导零。每个版本号至少包含一个字符。修订号从左到右编号,下标从 0 开始,最左边的修订号下标为 0,下一个修订号下标为 1,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。 比

题目描述

给你两个版本号 version1version2,请你比较它们。

版本号由一个或多个修订号组成,各修订号由一个 ‘.’ 连接。每个修订号由 多位数字 组成,可能包含 前导零。每个版本号至少包含一个字符。修订号从左到右编号,下标从 0 开始,最左边的修订号下标为 0,下一个修订号下标为 1,以此类推。例如,2.5.330.1 都是有效的版本号。

比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较 忽略任何前导零后的整数值。也就是说,修订号 1 和修订号 001 相等。如果版本号没有指定某个下标处的修订号,则该修订号视为 0。例如,版本 1.0 小于版本 1.1,因为它们下标为 0 的修订号相同,而下标为 1 的修订号分别为 010 < 1

返回规则如下:

  • 如果 version1 > version2,返回 1
  • 如果 version1 < version2,返回 -1
  • 除此之外,返回 0

难度

中等

题目链接

点击在LeetCode中查看题目

示例

示例 1:

输入:version1 = "1.01", version2 = "1.001"
输出:0
解释:忽略前导零,"01" 和 "001" 都表示相同的整数 "1"

示例 2:

输入:version1 = "1.0", version2 = "1.0.0"
输出:0
解释:version1 没有指定下标为 2 的修订号,即视为 "0"

示例 3:

输入:version1 = "0.1", version2 = "1.1"
输出:-1
解释:version1 中下标为 0 的修订号是 "0",version2 中下标为 0 的修订号是 "1"。0 < 1,所以 version1 < version2

示例 4:

输入:version1 = "1.0.1", version2 = "1"
输出:1

示例 5:

输入:version1 = "7.5.2.4", version2 = "7.5.3"
输出:-1

提示

  • 1 <= version1.length, version2.length <= 500
  • version1version2 仅包含数字和 '.'
  • version1version2 都是 有效版本号
  • version1version2 的所有修订号都可以存储在 32 位整数

解题思路

方法:分割字符串并比较

  1. 将两个版本号按照 . 分割成修订号数组
  2. 逐个比较对应位置的修订号大小
  3. 如果一个版本号的修订号数量少于另一个,则将缺失的部分视为0进行比较

关键点:

  1. 将字符串按 . 分割
  2. 将修订号转换为整数(处理前导零)
  3. 处理修订号数量不同的情况
  4. 根据比较结果返回相应的值

时间复杂度:O(max(m, n)),其中m和n分别是两个版本号的长度。 空间复杂度:O(m + n),需要存储分割后的修订号数组。

代码实现

C# 实现

public class Solution {
    public int CompareVersion(string version1, string version2) {
        string[] revisions1 = version1.Split('.');
        string[] revisions2 = version2.Split('.');
        
        int length = Math.Max(revisions1.Length, revisions2.Length);
        
        for (int i = 0; i < length; i++) {
            int rev1 = i < revisions1.Length ? int.Parse(revisions1[i]) : 0;
            int rev2 = i < revisions2.Length ? int.Parse(revisions2[i]) : 0;
            
            if (rev1 > rev2) {
                return 1;
            } else if (rev1 < rev2) {
                return -1;
            }
        }
        
        return 0;
    }
}

Python 实现

class Solution:
    def compareVersion(self, version1: str, version2: str) -> int:
        revisions1 = version1.split('.')
        revisions2 = version2.split('.')
        
        length = max(len(revisions1), len(revisions2))
        
        for i in range(length):
            rev1 = int(revisions1[i]) if i < len(revisions1) else 0
            rev2 = int(revisions2[i]) if i < len(revisions2) else 0
            
            if rev1 > rev2:
                return 1
            elif rev1 < rev2:
                return -1
        
        return 0

C++ 实现

class Solution {
public:
    int compareVersion(string version1, string version2) {
        vector<int> revisions1 = split(version1);
        vector<int> revisions2 = split(version2);
        
        int length = max(revisions1.size(), revisions2.size());
        
        for (int i = 0; i < length; i++) {
            int rev1 = i < revisions1.size() ? revisions1[i] : 0;
            int rev2 = i < revisions2.size() ? revisions2[i] : 0;
            
            if (rev1 > rev2) {
                return 1;
            } else if (rev1 < rev2) {
                return -1;
            }
        }
        
        return 0;
    }
    
private:
    vector<int> split(const string& version) {
        vector<int> result;
        istringstream iss(version);
        string token;
        
        while (getline(iss, token, '.')) {
            result.push_back(stoi(token));
        }
        
        return result;
    }
};

性能分析

各语言实现的性能对比:

实现语言 执行用时 内存消耗 特点
C# 84 ms 38.2 MB 实现简洁,性能适中
Python 36 ms 15.1 MB 代码最简洁
C++ 0 ms 6.1 MB 性能最优

补充说明

代码亮点

  1. 使用分割字符串的方式处理版本号
  2. 处理了前导零和缺失修订号的情况
  3. 代码简洁明了,易于理解

常见错误

  1. 没有正确处理前导零
  2. 没有处理修订号数量不同的情况
  3. 直接比较字符串而不是数值,导致比较结果错误

相关题目