题目的主要信息:
- 给出2个版本号version1和version2,比较它们的大小
- 版本号是由修订号组成,修订号与修订号之间由一个"."连接
- 修订号可能有前导0,按从左到右的顺序依次比较它们的修订号,比较修订号时,只需比较忽略任何前导零后的整数值
- 如果版本号没有指定某个下标处的修订号,则该修订号视为0
- 版本号中每一节可能超过int的表达范围
方法一:流输入截取
具体做法:
可以通过字符串流输入按点进行分割,将两个版本号字符串通过分割得到修订号的数组。然后同时遍历两个数组,将数组的字符串组成数字再判断数字的大小关系。
需要注意,有可能某一个版本号比另一个短,修订号更少,此时应该比较下标i与修订号数组,对于越界情况需要直接取0.
class Solution {
public:
int compare(string version1, string version2) {
vector<string> nums1;
vector<string> nums2;
istringstream sin1(version1);
istringstream sin2(version2);
string temp;
while(getline(sin1, temp, '.')) //流输入分割
nums1.push_back(temp);
while(getline(sin2, temp, '.'))
nums2.push_back(temp);
for(int i = 0; i < nums1.size() || i < nums2.size(); i++){
string s1 = i < nums1.size() ? nums1[i] : "0"; //较短的版本号取0
string s2 = i < nums2.size() ? nums2[i] : "0";
long long num1 = 0;
for(int i = 0; i < s1.length(); i++) //字符串转数字
num1 = num1 * 10 + (s1[i] - '0');
long long num2 = 0;
for(int i = 0; i < s2.length(); i++)
num2 = num2 * 10 + (s2[i] - '0');
if(num1 > num2) //比较数字大小
return 1;
if(num1 < num2)
return -1;
}
return 0;
}
};
复杂度分析:
- 时间复杂度:,其中和分别为两个字符串的长度,流输入相当于遍历字符串,复杂度选取较高值
- 空间复杂度:,使用了记录分割后修订号的数组,最坏长度为二者原本字符串长度最大值
方法二:遍历直接截取
具体做法:
利用两个指针表示字符串的下标,分别遍历两个字符串,每次截取点之前的数字字符组成数字,因为int会溢出,这里采用long long记录数字,然后比较两个数字大小,根据大小关系返回1或者-1,如果全部比较完都无法比较出大小关系,则返回0.
class Solution {
public:
int compare(string version1, string version2) {
int n1 = version1.size();
int n2 = version2.size();
int i = 0, j = 0;
while(i < n1 || j < n2){//直到某个字符串结束
long long num1 = 0;
while(i < n1 && version1[i] != '.'){ //从下一个点前截取数字
num1 = num1 * 10 + (version1[i] - '0');
i++;
}
i++; //跳过点
long long num2 = 0;
while(j < n2 && version2[j] != '.'){ //从下一个点前截取数字
num2 = num2 * 10 + (version2[j] - '0');
j++;
}
j++; //跳过点
if(num1 > num2) //比较数字大小
return 1;
if(num1 < num2)
return -1;
}
return 0; //版本号相同
}
};
复杂度分析:
- 时间复杂度:,其中和分别为两个字符串的长度,遍历两个字符串,复杂度选取较高值
- 空间复杂度:,无额外空间