每日一题——字符串变形
字符串变形
- 题目描述
- 数据范围
- 要求
- 示例
- 示例1
- 示例2
- 示例3
- 解题思路
- 代码实现
- 复杂度分析
- 相关要点
题目描述
对于一个长度为 n 的字符串,需要进行以下变形操作:
- 将字符串中由空格隔开的单词反序排列
- 反转每个字符的大小写
数据范围
- 1 ≤ n ≤ 10^6
- 字符串中只包括大写英文字母、小写英文字母、空格
要求
- 空间复杂度:O(n)
- 时间复杂度:O(n)
示例
示例1
输入:"This is a sample",16
输出:"SAMPLE A IS tHIS"
示例2
输入:"nowcoder",8
输出:"NOWCODER"
示例3
输入:"iOS",3
输出:"Ios"
解题思路
-
整体思路:
- 先将整个字符串反转
- 遍历字符串,对每个字符进行大小写转换
- 对每个单词进行反转
-
具体步骤:
- 定义一个反转函数 reverse,用于反转字符串指定区间的字符
- 先将整个字符串反转
- 遍历字符串:
- 遇到非空格字符时,转换大小写
- 遇到空格时,反转前面的单词
- 处理最后一个单词
代码实现
void reverse(char* s, int head, int tail) {
while (head < tail) {
char temp = s[head]; // 保存头部字符
s[head] = s[tail]; // 将尾部字符移到头部
s[tail] = temp; // 将保存的头部字符移到尾部
head++; // 头部指针向右移动
tail--; // 尾部指针向左移动
}
}
char* trans(char* s, int n) {
if (n == 0)
return ""; // 如果字符串长度为0,直接返回空字符串
// 先将整个字符串反转
reverse(s, 0, n - 1);
int j = 0, i; // j 用于记录单词的长度,i 用于遍历字符串
int mark; // mark 用于记录最后一个空格的位置
// 遍历处理每个字符
for (i = 0; i < n; i++) {
if (s[i] != ' ') { // 如果当前字符不是空格
// 转换大小写
if (s[i] >= 'a' && s[i] <= 'z') {
s[i] = s[i] - 32; // 小写转大写(ASCII 码差值为32)
} else {
s[i] = s[i] + 32; // 大写转小写
}
j++; // 单词长度加1
} else { // 如果遇到空格
// 遇到空格,反转前面的单词
reverse(s, i - j, i - 1); // 反转当前单词
j = 0; // 重置单词长度
mark = i; // 记录空格位置
}
}
// 处理边界情况
if (i == j) { // 如果整个字符串是一个单词(没有空格)
reverse(s, 0, n - 1); // 反转整个单词
}
if (mark != 0) { // 如果字符串中有空格
reverse(s, mark + 1, n - 1); // 反转最后一个单词
}
return s; // 返回处理后的字符串
}
复杂度分析
- 时间复杂度:O(n)
- 整体反转一次:O(n)
- 遍历处理字符:O(n)
- 单词反转:每个字符最多被反转两次,O(n)
- 空间复杂度:O(1)
- 只使用了常数额外空间
相关要点
-
字符串处理技巧
- 使用双指针进行字符串反转
- ASCII码转换实现大小写转换
- 空格作为单词分隔符的处理
-
边界情况处理
- 空字符串的处理
- 只有一个单词的情况
- 最后一个单词的处理