Easy
题目描述
给你一个由数字和字母以及破折号组成的字符串 s,其中的字符串由 n 个破折号分隔成 n + 1 组。同时给你一个整数 k。
我们想要重新格式化字符串 s,使每组都正好包含 k 个字符,除了第一组,它的长度可以少于 k,但仍必须至少包含一个字符。此外,两个组之间必须插入一个破折号,并且应该将所有小写字母转换为大写字母。
返回重新格式化的许可证密钥。
示例 1:
输入:s = "5F3Z-2e-9-w", k = 4
输出:"5F3Z-2E9W"
解释:字符串 s 被分成了两部分,每部分 4 个字符。
注意,两个额外的破折号是不需要的,可以删除。
示例 2:
输入:s = "2-5g-3-J", k = 2
输出:"2-5G-3J"
解释:字符串 s 被分成了三部分,每部分有 2 个字符,除了第一部分,因为它可以更短,如上所述。
提示:
1 <= s.length <= 10^5s由英文字母、数字和破折号'-'组成1 <= k <= 10^4
解题思路
这是一道字符串处理问题,核心思路是从右向左组织字符。
解题思路:
- 预处理:首先去除所有破折号,并将所有字母转为大写
- 从右向左分组:从处理后的字符串末尾开始,每
k个字符为一组 - 构建结果:将分组用破折号连接,注意第一组可能不足
k个字符
关键点:
- 从右向左处理可以确保除第一组外,其他组都恰好有
k个字符 - 使用栈或逆序处理来构建最终结果
- 需要特别处理边界情况(如空字符串、只有破折号等)
算法步骤:
- 遍历原字符串,跳过破折号,收集有效字符并转大写
- 从收集到的字符末尾开始,每
k个字符插入一个破折号 - 将结果逆序得到最终答案
这种从右向左的处理方式确保了分组的正确性,避免了复杂的长度计算。
代码实现
class Solution {
public:
string licenseKeyFormatting(string s, int k) {
string chars;
// 收集所有有效字符并转大写
for (char c : s) {
if (c != '-') {
chars += toupper(c);
}
}
if (chars.empty()) return "";
string result;
int count = 0;
// 从右向左处理
for (int i = chars.length() - 1; i >= 0; i--) {
if (count == k) {
result += '-';
count = 0;
}
result += chars[i];
count++;
}
// 结果是逆序的,需要反转
reverse(result.begin(), result.end());
return result;
}
};
class Solution:
def licenseKeyFormatting(self, s: str, k: int) -> str:
# 去除破折号并转大写
chars = ''.join(c.upper() for c in s if c != '-')
if not chars:
return ""
result = []
count = 0
# 从右向左处理
for i in range(len(chars) - 1, -1, -1):
if count == k:
result.append('-')
count = 0
result.append(chars[i])
count += 1
# 结果是逆序的,需要反转
return ''.join(reversed(result))
public class Solution {
public string LicenseKeyFormatting(string s, int k) {
StringBuilder chars = new StringBuilder();
// 收集所有有效字符并转大写
foreach (char c in s) {
if (c != '-') {
chars.Append(char.ToUpper(c));
}
}
if (chars.Length == 0) return "";
StringBuilder result = new StringBuilder();
int count = 0;
// 从右向左处理
for (int i = chars.Length - 1; i >= 0; i--) {
if (count == k) {
result.Append('-');
count = 0;
}
result.Append(chars[i]);
count++;
}
// 结果是逆序的,需要反转
char[] arr = result.ToString().ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
}
var licenseKeyFormatting = function(s, k) {
let cleaned = s.replace(/-/g, '').toUpperCase();
if (cleaned.length === 0) return '';
let result = [];
let count = 0;
for (let i = cleaned.length - 1; i >= 0; i--) {
if (count === k) {
result.unshift('-');
count = 0;
}
result.unshift(cleaned[i]);
count++;
}
return result.join('');
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历字符串两次,n为字符串长度 |
| 空间复杂度 | O(n) | 需要额外空间存储处理后的字符和结果 |