字符串
反转字符串
- 前提
- 原地修改输入数组
void reverseString(char* s, int sSize) {
char tmp;
int i = 0;
int j = sSize - 1;
while (i < sSize/2){
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
i++;
j--;
}
}
反转字符串2
解法一
计数器跨段
char* reverseStr(char* s, int k) {
int cnt = 0;
int size = strlen(s);
while (size > 0){
int subsize = size < k ? size : k;
int i = cnt*2*k;
int j = cnt*2*k + subsize - 1;
int mid = cnt*2*k + subsize/2;
while (i < mid){
char tmp = s[i];
s[i] = s[j];
s[j] = tmp;
i++;
j--;
}
size = size - 2*k;
cnt++;
}
return s;
}
解法二
for循环步长跨段
char * reverseStr(char * s, int k){
int len = strlen(s);
for (int i = 0; i < len; i += (2 * k)) {
//判断剩余字符是否少于 k
k = i + k > len ? len - i : k;
int left = i;
int right = i + k - 1;
while (left < right) {
char temp = s[left];
s[left++] = s[right];
s[right--] = temp;
}
}
return s;
}
替换数字(ACM)
-
要点
-
很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处:
- 不用申请新数组。
- 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
-
字符串末尾要加上\0,申请内存要预留长度
-
C语言没有
'0' <= s[i] <= '9'
的格式,得写成s[i] >= '0' && s[i] <= '9'
-
记得释放内存
-
数组别名是常量,无法将&array作为二维指针传递
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char replaceNumInStr(char **s, int sizeS){
int cnt = 0;
int i;
for (i = 0; i < sizeS; i++){
if ((*s)[i] >= '0' && (*s)[i] <= '9'){
cnt++;
}
}
int newSize = cnt*6 + sizeS - cnt;
*s = (char *)realloc(*s, (sizeof(char)*newSize+1));
int cur = newSize-1;
for (i = sizeS-1; i >=0; i--){
if ((*s)[i] >= '0' && (*s)[i] <= '9'){
(*s)[cur--] = 'r';
(*s)[cur--] = 'e';
(*s)[cur--] = 'b';
(*s)[cur--] = 'm';
(*s)[cur--] = 'u';
(*s)[cur--] = 'n';
}
else{
(*s)[cur--] = (*s)[i];
}
}
return newSize;
}
void main(){
int sizeStr = 0;
char *str= malloc(sizeof(char)*10000);
fgets(str, 10000, stdin);
str[strcspn(str, "\n")] = '\0';
sizeStr = replaceNumInStr(&str, strlen(str));
printf("%s\n", str);
free(str);
return;
}
反转字符串中的单词
- 前提
- 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括
- 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个
- 拓展:不使用额外的空间
- 解题思路
- 移除多余空格
- 移除元素使用快慢指针,快指针遍历搜索满足条件的元素,慢指针指向新数组的尾部
- 将整个字符串反转
- 相向双指针
- 将每个单词反转
- 整个字符串for循环遍历
- 单词相向双指针反转
- 移除多余空格
void removeSpaces(char *s){
int slow = 0;
int fast = 0;
for (;fast <= strlen(s); fast++){
if (s[fast] != ' '){
s[slow++] = s[fast];
}
else if (fast > 0 && s[fast-1] != ' '){
s[slow++] = s[fast];
}
}
s[slow-2] = s[slow-2] == ' ' ? '\0' : s[slow-2];
}
void reverseString(char *s, int slow, int fast){
char tmp;
while (slow < fast){
tmp = s[slow];
s[slow++] = s[fast];
s[fast--] = tmp;
}
}
char* reverseWords(char* s) {
removeSpaces(s);
reverseString(s, 0 , strlen(s)-1);
int slow = 0;
for (int i = 0; i <= strlen(s); i++){
if (s[i] == ' ' || s[i] == '\0'){
reverseString(s, slow, i-1);
slow = i + 1;
}
}
return s;
}
右旋转字符串
-
前提
- 拓展:不使用额外的空间
-
思路:
- 反转母串之后再反转子串
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverseString(char *s, int start, int end){
char tmp;
while (start < end){
tmp = s[start];
s[start++] = s[end];
s[end--] = tmp;
}
}
void main(){
int k;
char *s = malloc(sizeof(char)*10000);
scanf("%d", &k);
//跨行输入用getchar()吸收回车
getchar();
fgets(s, 10000, stdin);
s[strcspn(s, "\n")] = '\0';
reverseString(s, 0, strlen(s)-1);
reverseString(s, 0, k-1);
reverseString(s, k, strlen(s)-1);
printf("%s", s);
free(s);
return;
}