解法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
其他待续
欢迎和大家交流想法和见解,欢迎评论和小心心,加油哦!