比较两个版本号 version1 和 version2

原题描述:

比较两个版本号 version1 和 version2。
如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外返回 0。
你可以假设版本字符串非空,并且只包含数字和 . 字符。
. 字符不代表小数点,而是用于分隔数字序列。
例如,2.5 不是“两个半”,也不是“差一半到三”,而是第二版中的第五个小版本。
你可以假设版本号的每一级的默认修订版号为 0。例如,版本号 3.4 的第一级(大版本)和第二级(小版本)修订号分别为 3 和 4。其第三级和第四级修订号均为 0。
示例 1:
输入: version1 = “0.1”, version2 = “1.1”
输出: -1
示例 2:
输入: version1 = “1.0.1”, version2 = “1”
输出: 1
示例 3:
输入: version1 = “7.5.2.4”, version2 = “7.5.3”
输出: -1
示例 4:
输入:version1 = “1.01”, version2 = “1.001”
输出:0
解释:忽略前导零,“01” 和 “001” 表示相同的数字 “1”。
示例 5:
输入:version1 = “1.0”, version2 = “1.0.0”
输出:0
解释:version1 没有第三级修订号,这意味着它的第三级修订号默认为 “0”。
提示:
版本字符串由以点 (.) 分隔的数字字符串组成。这个数字字符串可能有前导零。
版本字符串不以点开始或结束,并且其中不会有两个连续的点。

思路:

  1. 字符串本身就有字典序,如果直接在字符串中把前导0去掉,则操作过程较为繁琐,还要判断两端的特殊情况。弃用,直接看2。
  2. 我想到用vector存储每位数字的方法,将2个string按照’.'分割,存放进vector中,然后通过给短的vector补0的方式,将2个vector的长度对齐。最后挨个比较2个vector的每个元素即可。
    代码如下:
#include <iostream>
#include <map>
#include <string>

using namespace std;

void compensate0(vector<int>& vec, int diff)
{
    for(int i = 0; i < diff; ++i)
    {
        vec.push_back(0);
    }
}

int compVector(vector<int> vec1, vector<int> vec2)
{
    int diff = abs((int)(vec1.size() - vec2.size()));
    if(vec1.size() < vec2.size())
    {
        compensate0(vec1, diff);
    }
    else
    {
        compensate0(vec2, diff);
    }
    for(int i = 0; i < vec1.size(); ++i)
    {
        if(vec1[i] > vec2[i])
        {
            return 1;
        }
        else if(vec1[i] < vec2[i])
        {
            return -1;
        }
    }
    return 0;
}

void getVector(string str, vector<int>& vec)
{
    while(str.find('.') != str.npos)
    {
        int pos = str.find('.');
        vec.push_back(stoi(str.substr(0, pos)));
        str = str.substr(pos + 1);
    }
    vec.push_back(stoi(str));
}

int compareVersion(string version1, string version2) {
    vector<int> vec1;
    vector<int> vec2;
    getVector(version1, vec1);
    getVector(version2, vec2);
    return compVector(vec1, vec2);
}

static void AssertVersion(string v1, string v2, int res)
{

    if(compareVersion(v1, v2) != res)
    {
        cout << "ERR! v1 is " << v1 << " , v2 is " << v2 << ", res is " << compareVersion(v1, v2) << endl;
    }
    else
    {
        cout << "OK" << endl;
    }
}

int main()
{
    AssertVersion("0.1", "1.1", -1);
    AssertVersion("1.0.1", "1", 1);
    AssertVersion("7.5.2.4", "7.5.3", -1);
    AssertVersion("1.01", "1.001", 0);

    return 0;
}

运行结果如下:

OK
OK
OK
OK

其实此时就是LeetCode165。官方给的解答很简洁,但是不容易想到。我仿照官方自己写了下,如下:

class Solution {
public:
//当i或者j有一个超出范围后,while还在执行,++i或者++j其实已经没有意义了,但是不用管它,只要答案对就行了。
    int compareVersion(string version1, string version2) {
        int i = 0, j = 0;
        while(i < version1.size() || j < version2.size())
        {
            int sum1 = 0, sum2 = 0;
            for(; i < version1.size() && version1[i] != '.'; ++i)
            {
                sum1 = sum1 * 10 + (version1[i] - '0');
            }
            ++i; //跳过'.'
            for(; j < version2.size() && version2[j] != '.'; ++j)
            {
                sum2 = sum2 * 10 + (version2[j] - '0');
            }
            ++j; //跳过'.'
            cout << "sum1 is " << sum1 << ", sum2 is " << sum2 << endl;
            if(sum1 > sum2)
            {
                return 1;
            }
            else if(sum2 > sum1)
            {
                return -1;
            }
        }
        return 0;
    }
};