题目的主要信息:

  • 给出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;
    }
};

复杂度分析:

  • 时间复杂度:O(max(n,m))O(max(n,m)),其中mmnn分别为两个字符串的长度,流输入相当于遍历字符串,复杂度选取较高值
  • 空间复杂度:O(max(n,m))O(max(n,m)),使用了记录分割后修订号的数组,最坏长度为二者原本字符串长度最大值

方法二:遍历直接截取

具体做法:

利用两个指针表示字符串的下标,分别遍历两个字符串,每次截取点之前的数字字符组成数字,因为int会溢出,这里采用long long记录数字,然后比较两个数字大小,根据大小关系返回1或者-1,如果全部比较完都无法比较出大小关系,则返回0.

alt

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; //版本号相同
    }
};

复杂度分析:

  • 时间复杂度:O(max(n,m))O(max(n,m)),其中mmnn分别为两个字符串的长度,遍历两个字符串,复杂度选取较高值
  • 空间复杂度:O(1)O(1),无额外空间