165. 比较版本号 三种解法

解法1:不调用任何方法,赤手择数字,比较每节版本号的字符串

class Solution {
private:
    //得到每节版本号的有效起始地址[left, right)
    bool getNumIndex(string s, int len, int& left, int& right) {
        if (left >= len)                                          //已无有效版本号
            return false;
        while (left < len-1 && s[left] == '0' && s[left+1] != '.')//每节至少留一位数字,其他数字位若为0则右移
            left++;
        right = left + 1;
        while (right < len && s[right] != '.')
            right++;
        return true;
    }
public:
    int compareVersion(string version1, string version2) {
        int len1 = version1.size();
        int len2 = version2.size();
        int left1 = 0, right1;
        int left2 = 0, right2;
        bool flag1 = getNumIndex(version1, len1, left1, right1);//是否还有某节版本号需要比
        bool flag2 = getNumIndex(version2, len2, left2, right2);
        while (flag1 && flag2) {
            int size1 = right1 - left1;                  //若有效版本号长度不一致,则长度较长者大
            int size2 = right2 - left2;
            if (size1 > size2)
                return 1;
            else if (size1 < size2)
                return -1;
            
            while (left1 < right1 && left2 < right2) {  // size1 == size2情况
                if (version1[left1] < version2[left2])
                    return -1;
                else if (version1[left1] > version2[left2])
                    return 1;
                left1++;
                left2++;
            }

            left1 = right1 + 1;                        //比下一节版本号
            left2 = right2 + 1;
            flag1 = getNumIndex(version1, len1, left1, right1);
            flag2 = getNumIndex(version2, len2, left2, right2);
        }
        if (flag1)
            while(flag1) {
                if (version1[left1] != '0')
                    return 1;
                left1 = right1 + 1;
                flag1 = getNumIndex(version1, len1, left1, right1);
            }
        if (flag2)
            while(flag2 = getNumIndex(version2, len2, left2, right2)) {
                if (version2[left2] != '0')
                    return -1;
                left2 = right2 + 1;
                flag2 = getNumIndex(version2, len2, left2, right2);
            }
        
        return 0;
    }
};

      其中,

1:大版本号以‘.’分的数字版本号作者称为节。

2:所谓每节版本号的有效起始地址,这个有效指的是,若该节版本号为数字0,则left就指向最后这个有效0,若为类似"0020"的版本号,则left久指向2这个首个非0数字。

3:getNumIndex()根据传入的left找该节的有效版本号,找的过程中会修改left,也会给出right值,这个right指的是有效数字还是有效数字的下一位,可自行规定,本程序指的是有效数字下一位。

4:因为getNumIndex()返回的是有效版本号,所以版本号的长度不一致时,就已经能说明大小,不用再一位位比较。

解法2:利用string方法,将字符串版本号转换为整型

class Solution {
private:
    vector<int> split(const string& s, char separa) {
        vector<int> res;
        int len = s.size();
        if(len == 0)
            return res;
        int start = 0;
        size_t pos;                           //若记不得类型,可在赋值时候用auto
        while (start < len) {
            pos = s.find(separa, start);
            if (pos != string::npos) {
                int tmp = stoi(s.substr(start, pos - start));
                res.push_back(tmp);
                start = pos + 1;
            } else {
                int tmp = stoi(s.substr(start, len - start));
                res.push_back(tmp);
                break;
            }
        }

        return res;
    }
public:
    int compareVersion(string version1, string version2) {
        vector<int> nums1 = split(version1, '.');
        vector<int> nums2 = split(version2, '.');

        int len1 = nums1.size();
        int len2 = nums2.size();
        int maxLen = len1 > len2 ? len1 : len2;
        int num1 = 0, num2 = 0;
        for (int i = 0; i < maxLen; i++) {
            if (i < len1)
                num1 = nums1[i];
            else
                num1 = 0;
            if (i < len2)
                num2 = nums2[i];
            else
                num2 = 0;
            
            if(num1 > num2)
                return 1;
            else if (num1 < num2)
                return -1;
        }
        
        return 0;
    }
};

解法3:在解法2的基础上,用stringstream类型重写split()

class Solution {
private:
    vector<int> split(const string& s, char separa) {
        vector<int> res;
        int len = s.size();
        if(len == 0)
            return res;

        string tmp;
        stringstream ss(s);
        while(getline(ss, tmp, separa)) {
            int num = stoi(tmp);
            res.push_back(num);
        }

        return res;
    }
public:
    int compareVersion(string version1, string version2) {
        vector<int> nums1 = split(version1, '.');
        vector<int> nums2 = split(version2, '.');

        int len1 = nums1.size();
        int len2 = nums2.size();
        int maxLen = len1 > len2 ? len1 : len2;
        int num1 = 0, num2 = 0;
        for (int i = 0; i < maxLen; i++) {
            if (i < len1)
                num1 = nums1[i];
            else
                num1 = 0;
            if (i < len2)
                num2 = nums2[i];
            else
                num2 = 0;
            
            if(num1 > num2)
                return 1;
            else if (num1 < num2)
                return -1;
        }
        
        return 0;
    }
};

 

附录:string常用方法说明

str.substr(startpos,length); //从str的startpos位置截取length长度的字符串

str.find('a')                          //默认从位置0(即第1个字符)开始查找

str.find('a', i)                      //在st1中,从位置i(包括位置i)开始,查找a,返回首次匹配的位置,若查找不到,返回string::npos,不是NULL

其他待续

                   欢迎和大家交流想法和见解,欢迎评论和小心心,加油哦! 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值