问题分析
给定两个版本号字符串 version1 和 version2,我们需要:
- 将这两个版本号按
.分割成修订号数组。 - 比较修订号,较大的版本号被认为更“新”。
- 如果两个版本号在所有修订号上相等,则认为它们相等。
思路
-
分割版本号:版本号是由点分隔的数字组成,例如
"1.0.1"。首先,我们可以通过split(".")将版本号字符串分割为一个字符串数组,每个元素表示版本号的一个部分。 -
比较各个修订号:由于两个版本号的修订号部分长度可能不同,我们需要确保即使某个版本号较短,我们也能进行比较。在进行比较时,缺少的修订号可以认为是 0。
-
返回结果:通过逐个比较修订号:
- 如果某个修订号大于另一个版本对应修订号,则当前版本号较大,返回
1。 - 如果某个修订号小于另一个版本对应修订号,则当前版本号较小,返回
-1。 - 如果所有修订号相等,则返回
0。
- 如果某个修订号大于另一个版本对应修订号,则当前版本号较大,返回
代码详解
java
public class Main {
public static void main(String[] args) {
System.out.println(solution("0.1", "1.1") == -1); // 版本 0.1 < 1.1
System.out.println(solution("1.0.1", "1") == 1); // 版本 1.0.1 > 1
System.out.println(solution("7.5.2.4", "7.5.3") == -1); // 版本 7.5.2.4 < 7.5.3
System.out.println(solution("1.0", "1.0.0") == 0); // 版本 1.0 == 1.0.0
}
public static int solution(String version1, String version2) {
// 1. 将版本号按 '.' 分割成修订号数组
String[] v1Parts = version1.split("\."); // version1 按 '.' 分割
String[] v2Parts = version2.split("\."); // version2 按 '.' 分割
// 2. 获取两个版本号修订号数组的最大长度
int maxLength = Math.max(v1Parts.length, v2Parts.length); // 找出较长的修订号数组长度
// 3. 遍历修订号数组,逐个比较修订号
for (int i = 0; i < maxLength; i++) {
// 4. 获取当前修订号,如果超出数组长度,则视为 0
int v1Part = (i < v1Parts.length) ? Integer.parseInt(v1Parts[i]) : 0; // 当前修订号(version1),如果没有则默认为0
int v2Part = (i < v2Parts.length) ? Integer.parseInt(v2Parts[i]) : 0; // 当前修订号(version2),如果没有则默认为0
// 5. 比较当前修订号
if (v1Part > v2Part) {
return 1; // 如果 version1 的修订号大于 version2 的,返回 1
} else if (v1Part < v2Part) {
return -1; // 如果 version1 的修订号小于 version2 的,返回 -1
}
// 如果当前修订号相等,继续比较下一个修订号
}
// 6. 如果所有修订号都相等,返回 0
return 0; // 如果所有修订号都相等,返回 0
}
}
详细解析
-
split("\."):version1.split("\.")将版本号字符串按.分割,返回一个数组。例如,"1.0.1"会分割成数组["1", "0", "1"]。split("\.")中的\.是转义字符,因为.在正则表达式中是特殊字符,表示任意单个字符,因此需要转义成\.来表示字面上的点字符。
-
Math.max(v1Parts.length, v2Parts.length):- 计算两个版本号数组的最大长度。不同版本号的修订部分可能不等长,比如
"1.0"和"1.0.0",这时需要视缺少的修订号为0。
- 计算两个版本号数组的最大长度。不同版本号的修订部分可能不等长,比如
-
修订号比较:
- 使用
Integer.parseInt(v1Parts[i])和Integer.parseInt(v2Parts[i])将修订号从字符串转换为整数。若某个版本号数组长度较短,则该部分取值0,通过(i < v1Parts.length) ? Integer.parseInt(v1Parts[i]) : 0和(i < v2Parts.length) ? Integer.parseInt(v2Parts[i]) : 0来处理。
- 使用
-
return 1、return -1、return 0:- 如果某个修订号在
version1中大于对应修订号在version2中,返回1(version1较大)。 - 如果某个修订号在
version1中小于对应修订号在version2中,返回-1(version2较大)。 - 如果遍历完所有修订号后仍然没有分出大小,则返回
0,表示两个版本相等。
- 如果某个修订号在
图解
-
输入:
version1 = "0.1",version2 = "1.1"-
分割后:
v1Parts = ["0", "1"]v2Parts = ["1", "1"]
-
比较修订号:
- 第一部分
0 < 1,因此返回-1,表示version1较小。
- 第一部分
-
-
输入:
version1 = "1.0.1",version2 = "1"-
分割后:
v1Parts = ["1", "0", "1"]v2Parts = ["1"]
-
比较修订号:
- 第一部分
1 == 1 - 第二部分
0 < 0,返回1,表示version1较大。
- 第一部分
-
-
输入:
version1 = "7.5.2.4",version2 = "7.5.3"-
分割后:
v1Parts = ["7", "5", "2", "4"]v2Parts = ["7", "5", "3"]
-
比较修订号:
- 第一部分
7 == 7 - 第二部分
5 == 5 - 第三部分
2 < 3,返回-1,表示version2较大。
- 第一部分
-
-
输入:
version1 = "1.0",version2 = "1.0.0"-
分割后:
v1Parts = ["1", "0"]v2Parts = ["1", "0", "0"]
-
比较修订号:
- 第一部分
1 == 1 - 第二部分
0 == 0 - 第三部分没有对应修订号(默认为
0),所以返回0,表示两个版本相等。
- 第一部分
-
时间和空间复杂度
- 时间复杂度:
O(n), 其中n是版本号字符串中最长的部分数(即修订号的数量)。每次对两个修订号部分进行比较,时间复杂度为O(n)。 - 空间复杂度:
O(n),用于存储分割后的版本号数组。
总结
这段代码的主要目标是通过分割和比较版本号的各个修订号部分,来实现版本号的比较。它处理了不同长度的版本号,并返回了正确的比较结果。