算法:字符串专项
1. 比较版本号#
nowcoder 题目链接
【题目描述】
牛客项目发布项目版本时会有版本号,比如1.02.11,2.14.4等等。现在给你2个版本号version1和version2,请你比较他们的大小。
版本号是由修订号组成,修订号与修订号之间由一个"."连接。1个修订号可能有多位数字组成,修订号可能包含前导0,且是合法的。例如,1.02.11,0.1,0.2都是合法的版本号。
每个版本号至少包含1个修订号。修订号从左到右编号,下标从0开始,最左边的修订号下标为0,下一个修订号下标为1,以此类推。比较规则:
- 比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较忽略任何前导零后的整数值。比如"0.1"和"0.01"的版本号是相等的
- 如果版本号没有指定某个下标处的修订号,则该修订号视为0。例如,"1.1"的版本号小于"1.1.1"。因为"1.1"的版本号相当于"1.1.0",第3位修订号的下标为0,小于1
- version1 > version2 返回1,如果 version1 < version2 返回-1,不然返回0.
数据范围:
1 <= version1.length, version2.length <= 1000
version1 和 version2 的修订号不会超过int的表达范围,即不超过 32 位整数 的范围示例1
输入:"1.1","2.1"
返回值:-1
说明:version1 中下标为 0 的修订号是 "1",version2 中下标为 0 的修订号是 "2" 。1 < 2,所以 version1 < version2,返回-1示例2
输入:"1.1","1.01"
返回值:0
说明:version2忽略前导0,为"1.1",和version相同,返回0
【思路】
- 既然是比较两个字符串每个点之间的数字是否相同,就直接遍历字符串比较,但是数字前导零不便于我们比较,因为我们不知道后面会出现多少前导零,因此应该将点之间的部分转化为数字再比较才方便。
- 可以先将 string 根据'.'划分为 vector
,利用库函数进行操作,也可以直接遍历,截取分隔符'.'之间的字符串,转换为 int,再比较。
#include <string>
#include <vector>
#include <algorithm>
using namespace ::std;
// using std::string;
class Solution
{
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 比较版本号
* @param version1 string字符串
* @param version2 string字符串
* @return int整型
*/
int compare(string version1, string version2)
{
vector<string> version1Vec = split(version1, ".");
vector<string> version2Vec = split(version2, ".");
int len = min(version1Vec.size(), version2Vec.size());
int i = 0;
for (; i < len; i++)
{
int version1Num = atoi(version1Vec[i].c_str());
int version2Num = atoi(version2Vec[i].c_str());
if (version1Num < version2Num)
return -1;
else if (version1Num > version2Num)
return 1;
}
// version1 长
while (i < version1Vec.size())
{
if (atoi(version1Vec[i++].c_str()) != 0)
return 1;
}
while (i < version2Vec.size())
{
if (atoi(version2Vec[i++].c_str()) != 0)
return -1;
}
return 0;
}
/**
* @param str 待分割的字符串
* @param pattern 以 pattern 来分割字符串
* @return 分割后的 vector<string> 容器
*/
vector<string> split(const string &str, const string &pattern)
{
vector<string> result;
if (str == "")
return result;
string strs = str + pattern; // 尾部加分割符,统一尾部操作
size_t pos = strs.find(pattern); // 第一个分隔符位置
while (pos != strs.npos) // find 函数若未在字符串中找到,返回 npos
{
string temp = strs.substr(0, pos); // 分割
result.push_back(temp);
strs = strs.substr(pos + 1, strs.size()); // 去掉已分割字符
pos = strs.find(pattern);
}
return result;
}
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 比较版本号
* @param version1 string字符串
* @param version2 string字符串
* @return int整型
*/
int compare2(string version1, string version2)
{
int ver1 = 0, ver2 = 0;
int len1 = version1.size(), len2 = version2.size();
int i = 0, j = 0;
while (i < len1 || j < len2)
{
while (i < len1 && version1[i] != '.')
{
ver1 = ver1 * 10 + (version1[i] - '0');
i++;
}
while (j < len2 && version2[j] != '.')
{
ver2 = ver2 * 10 + (version2[j] - '0');
j++;
}
if (ver1 < ver2)
return -1;
if (ver1 > ver2)
return 1;
i++;
j++;
ver1 = 0;
ver2 = 0;
}
return 0;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!