今天我们将在豆包MarsCode AI刷题平台上,完成《模版串匹配问题》与《K排序算法最小操作次数计算》这两个算法问题,通过这些练习提升用户解决此类问题的能力
《模版串匹配问题》题面如下:
问题理解
题目要求我们根据给定的模板串 s
和整数 k
,生成一个没有前导零的正整数,并且这个正整数是所有可能的匹配数中字典序第 k
小的。如果无法生成这样的数,则返回 -1
。
数据结构选择
- 字符串
s
:用于存储模板串。 - 向量
pos
:用于存储模板串中所有'?'
字符的位置。 - 字符串
ret
:用于存储生成的结果。
算法步骤
-
遍历模板串
s
:- 记录所有
'?'
字符的位置,存储在向量pos
中。
- 记录所有
-
处理前导
'?'
:- 如果模板串的第一个字符是
'?'
,则需要特别处理,因为不能有前导零。 - 计算可能的组合数
add
,即10
的pos.size() - 1
次方。 - 根据
k
计算出第k
小的数,并将其转换为字符串ret
。
- 如果模板串的第一个字符是
-
填充
'?'
字符:- 由后向前遍历
pos
,将ret
中的数字依次填充到s
中的'?'
位置。 - 如果
ret
中的数字用完了,则填充'0'
。
- 由后向前遍历
-
检查结果:
- 如果填充后的
s
以'0'
开头,或者ret
中的数字没有用完,则返回-1
。 - 否则,返回填充后的
s
。
- 如果填充后的
具体实现
std::string solution(std::string s, int k) {
// write code here
string ret;
vector<int> pos;
for(int i=0;i<s.size();i++){
if(s[i] == '?'){
pos.push_back(i);
}
}
if(s[0] == '?'){
int add = 1;
for(int i = 1;i < pos.size();i++){
add *= 10;
}
ret = to_string(add + k - 1);
} else {
ret = to_string(k - 1);
}
int retp=ret.size() - 1;
for(int p =pos.size() - 1;p >= 0;p--){
if(retp < 0){
s[pos[p]] = '0';
} else {
s[pos[p]] = ret[retp--];
}
}
return (s[0] == '0' || retp >= 0) ? "-1" : s;
}
《K排序算法最小操作次数计算》题面如下:
问题理解
题目要求我们计算最少需要多少次操作,才能将一个长度为 n
的排列由小到大排序。每次操作可以选择最多 k
个位置的数,将它们移除后,对剩余的数左对齐,然后将移除的数排序后放在数列的末尾。
解题思路
-
识别已排序部分:
- 首先,我们需要识别数组中已经按升序排列的部分。这部分不需要任何操作。
- 例如,对于数组
[1, 3, 5, 4, 2]
,已经按升序排列的部分是[1, 2]
。
-
计算未排序部分的长度:
- 未排序部分的长度是数组总长度减去已排序部分的长度。
- 例如,对于数组
[1, 3, 5, 4, 2]
,未排序部分是[3, 5, 4]
,长度为 3。
-
计算操作次数:
- 每次操作最多可以移除
k
个元素,因此我们需要计算最少需要多少次操作才能将未排序部分排序。 - 计算公式为:
(未排序部分的长度 + k - 1) / k
。这个公式确保我们向上取整,因为每次操作最多可以处理k
个元素。
- 每次操作最多可以移除
具体实现
int solution(int n, int k, std::vector<int> a) {
// write code here
int pos = 1;
for(int i : a){
if(i == pos){
pos++;
}
}
return (n - pos + 1 + k - 1) / k;
}
借助豆包MarsCode AI刷题平台,我们不仅高效地解决了《模版串匹配问题》和《K排序算法最小操作次数计算》,还加深了对相关算法和数据结构的理解,后续会借助豆包MarsCode AI给大家展示更多题目的解法。