原题
字符串中等1 种解法

#165比较版本号

逐段比较两个点分十进制版本号,忽略每段前导零和尾部零段。

#字符串#双指针

原题

给你两个 版本号字符串 version1version2 ,请你比较它们。版本号由被点 '.' 分开的修订号组成。修订号的值 是它 转换为整数 并忽略前导零。

比较版本号时,请按 从左到右的顺序 依次比较它们的修订号。如果其中一个版本字符串的修订号较少,则将缺失的修订号视为 0

返回规则如下:

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

示例 1:

输入:version1 = "1.2", version2 = "1.10"

输出:-1

解释:

version1 的第二个修订号为 "2",version2 的第二个修订号为 "10":2 < 10,所以 version1 < version2。

示例 2:

输入:version1 = "1.01", version2 = "1.001"

输出:0

解释:

忽略前导零,"01" 和 "001" 都代表相同的整数 "1"。

示例 3:

输入:version1 = "1.0", version2 = "1.0.0.0"

输出:0

解释:

version1 有更少的修订号,每个缺失的修订号按 "0" 处理。

提示:

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

查看原题

解题主线

  1. 每轮取出一个 revision;去掉前导零后先比较有效长度,再按字典序比较,可完全避免数值溢出。

解法 1:逐段字符串比较

双指针切出每个 revision,跳过前导零后比较有效位数与字符。

  • 时间复杂度: O(m + n)

  • 空间复杂度: O(1)

JAVA
final class Solution {
    public int compareVersion(String version1, String version2) {
        int first = 0;
        int second = 0;
        // 每轮同步比较一个 revision,缺失的尾段按空的零段处理。
        while (first < version1.length() || second < version2.length()) {
            int firstEnd = nextDot(version1, first);
            int secondEnd = nextDot(version2, second);
            // 跳过前导零后,剩余长度就是该段数值的有效位数。
            while (first < firstEnd && version1.charAt(first) == '0') first++;
            while (second < secondEnd && version2.charAt(second) == '0') second++;

            int firstLength = firstEnd - first;
            int secondLength = secondEnd - second;
            // 有效位数不同可直接判断大小,无需解析为可能溢出的整数。
            if (firstLength != secondLength) return firstLength > secondLength ? 1 : -1;
            // 位数相同时按高位到低位比较,等价于比较十进制数值。
            for (int offset = 0; offset < firstLength; offset++) {
                char left = version1.charAt(first + offset);
                char right = version2.charAt(second + offset);
                if (left != right) return left > right ? 1 : -1;
            }
            first = firstEnd + 1;
            second = secondEnd + 1;
        }
        return 0;
    }

    private int nextDot(String version, int start) {
        int index = start;
        while (index < version.length() && version.charAt(index) != '.') index++;
        return index;
    }
}

实现提示

  • 以字符串段比较替换旧 parseInt,消除 revision 超出 int 范围的风险。

边界与易错点

  • 旧实现 Integer.parseInt 在超长 revision 上可能溢出;字符串比较不依赖数值类型范围。
  • 缺失的尾部 revision 等价于 0。
  • 不能直接按整个版本字符串做字典序比较,例如 1.10 大于 1.2。

整理来源

由旧仓库源码复核、去重并整理;展示代码已按 Java 21 语义修正明显问题。

  • medium/Q165_compareVersion.java