字符串中等1 种解法
#165比较版本号
逐段比较两个点分十进制版本号,忽略每段前导零和尾部零段。
#字符串#双指针
原题
给你两个 版本号字符串 version1 和 version2 ,请你比较它们。版本号由被点 '.' 分开的修订号组成。修订号的值 是它 转换为整数 并忽略前导零。
比较版本号时,请按 从左到右的顺序 依次比较它们的修订号。如果其中一个版本字符串的修订号较少,则将缺失的修订号视为 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 <= 500version1和version2仅包含数字和'.'version1和version2都是 有效版本号version1和version2的所有修订号都可以存储在 32 位整数 中
解题主线
- 每轮取出一个 revision;去掉前导零后先比较有效长度,再按字典序比较,可完全避免数值溢出。
解法 1:逐段字符串比较
双指针切出每个 revision,跳过前导零后比较有效位数与字符。
-
时间复杂度: O(m + n)
-
空间复杂度: O(1)
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