day_08
传送门
-
344 - 反转字符串 - 题目链接/文章讲解/视频讲解
-
541 - 反转字符串 II - 题目链接/文章讲解/视频讲解
-
5 - 替换空格 - 题目链接/文章讲解/视频讲解
-
151 - 翻转字符串里的单词 - 题目链接/文章讲解/视频讲解
344. 反转字符串
- 前后双指针同时遍历,交换左右边的值,复杂度 O(n)
- 交换方式一:申请一个空间的char 保存数据,进行交换
- 交换方式二:两数异或操作,位运算实现
- 库函数的时间复杂度也是 O(n)
- 代码实现
- C语言
void reverseString(char* s, int sSize){ int i = 0; int j = sSize - 1; while ( i < j) { s[i] ^= s[j]; // 异或运算进行交换 s[j] ^= s[i]; s[i] ^= s[j]; i++; j--; } }
- java
class Solution { public void reverseString(char[] s) { int i = 0; int j = s.length - 1; while ( i < j) { s[i] ^= s[j]; // 异或运算进行交换 s[j] ^= s[i]; s[i] ^= s[j]; i++; j--; } } }
541. 反转字符串 II
- 是上一题的升级版,第一眼看过去有两个思路
- 递归处理,每次处理 2k 个字符量,总是出错,呜呜呜
- 循环处理,同上每次 2k 字符量处理,每次循环 +2k
- 代码实现
char * reverseStr(char * s, int k){
int size = strlen(s); // 先得到字符串的长度
int start = 0; // 每一组要处理的数组的起始下标
int end = 0; // 每一组要处理的数组的结束下标
for (int i = 0; i < size; i += 2*k){ // 给数组切片
i + k >= size? k : i; // 其实下标+k,用来判断当前数组的长度与 k 的关系
if (i + k >= size){ // 处理剩余数组长度<= k的数组
reverse(s, i, size - 1);
continue;
}
reverse(s, i, i + k - 1); // 反之,都是只处理前 k 个字符
}
}
// 交换数组值的函数。需要数组进行修改
void reverse(char* s, int start, int end){
for (int i = start, j = end; i < j; i++, j--){
char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
5. 替换空格
-
库函数很容易实现,但是这个问题是实现这样的一个库函数,所以不用库函数
-
思路
- 数组的大小是否需要扩容?如何扩容?
- C 里面直接申请一个指定大小的数组
- java 同样里可以申请一个指定大小数组
- java 里还可以用 stringBuilder,遍历原先的字符串,直接从左到右替换目标值
- 扩容完毕后,如何处理呢?
- 左到右赋值,相对简便不少
- 右到左的双指针赋值,给数组额外申请一部分空间,推荐选这个
- 数组的大小是否需要扩容?如何扩容?
-
代码实现
- C语言 (为什么这题里,不能使用 while(*s) ? 用了会报错 heap-buffer-overflow? 为什么呀)
- 原因:s++的时候,首地址指针已被改变,所以读取的时候才会出问题!!!C指针使用时要注意呀!
// 替换空格 char* replaceSpace(char* s){ int count = 0; // 记录空格的个数 int strLen = strlen(s); // 记录字符串长度 for (int i = 0; i < strLen; i++){ count += ( s[i] == ' '); } // 统计个数是为了扩容,C里的字符串需要手动添加 '\0' 不要忘 ! int newArrLen = count * 2 + strLen; char* res = malloc(sizeof(char) * newArrLen + 1); // 开始双指针 int left = strLen - 1; int right = newArrLen - 1; res[newArrLen] = '\0'; while (left >= 0){ // 遍历原先的数组,给扩容后的数组赋值 if (s[left] == ' '){ res[right--] = '0'; res[right--] = '2'; res[right--] = '%'; left--; continue; } res[right--] = s[left--]; } return res; }
- C语言 (为什么这题里,不能使用 while(*s) ? 用了会报错 heap-buffer-overflow? 为什么呀)
151. 翻转字符串里的单词
-
思路:快慢指针处理
- 先处理空格
- 默认每遇到一个单词的时候,slow先赋值一个空格,再快指针赋值慢指针
- 整体反转,依旧使用快慢指针处理
- 单个单词反转,快慢指针处理
- 先处理空格
-
C语言代码实现
// 处理字符串反转
void reverse(char *s, int start, int end){
int i = start;
int j = end;
for ( ; i < j ; i++ , j--){
char temp;
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
// 处理字符串中的多余空格,使用快慢指针处理
// C语言字符串的结尾有一个'\0'就表示该字符串结束了
void dealSpace(char* s, int size){
int slow = 0;
int fast = 0;
for ( ; fast < size; fast++){ // 快指针遍历,赋值需要的数值给慢指针
if (s[fast] != ' '){ // 找到单词的第一个字母
if (slow != 0){
s[slow++] = ' '; // 给每一个单词前面添加空格
}
while (s[fast] != ' ' && s[fast]!='\0'){ // 处理每一个单词,
s[slow++] = s[fast++];
}
fast--; // 记得回退一步fast
}
}
s[slow] = '\0'; // 给字符串末尾添加 '\0'
}
// 开始反转单词,先处理空格,再反转所有的字符串,最后反转每个单词
char * reverseWords(char * s){
int size = strlen(s);
dealSpace(s, size); // 处理完所有的空格了
size = strlen(s); // 空格处理完后,字符串的长度会发生改变!
reverse(s, 0, size - 1); // 字符串整体反转
int wordStart = 0; // 快慢指针反转单个单词
int wordEnd = 0;
// <= 是为了让fast可以指到 '\0',然后对最后一个单词处理,如果是 < ,if走不进去,最后一个单词不会被处理
for ( ; wordEnd <= size; wordEnd++){
if (s[wordEnd] == ' ' || s[wordEnd] == '\0'){
reverse(s, wordStart, wordEnd - 1);
wordStart = wordEnd + 1 ;
}
}
return s;
}
剑指Offer58-II.左旋转字符串
-
思路 1 :直接申请新数组处理,两个指针一前一后读完字符串赋值给新数组
-
思路 2 :不申请额外O(n) 的空间处理
- 先看看矩阵里的转置是怎么回事
- 矩阵的转置操作是将元素的位置进行颠倒 A = (AT)
- 在字符串里我们也可以看作字符串是一个一维矩阵,无论是否转置,我们都是用一个指针遍历这个一维矩阵的
- 同时这个矩阵还可以看作是好几个分块矩阵拼起来的结果
- 即 [ M ] = [ A B C ] ====> M = abcdef, A = ab, B = cd, C = ef
- (AB)T = BTAT
- 目标:AB ======> BA
- 过程如下
- AB ===> ATBT ===> (ATBT)T ===> BA
- 翻译过来就是:先反转前面的部分,再反转后面的部分,最后全部反转
- 过程如下
- 先看看矩阵里的转置是怎么回事
-
C语言代码实现如下
// AB => A^T B^T => (A^T B^T)^T => BA
// 处理字符串反转
void reverse(char *s, int start, int end){
int i = start;
int j = end;
for ( ; i < j ; i++ , j--){
char temp;
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
char* reverseLeftWords(char* s, int n){
reverse(s, 0 , n-1);
reverse(s, n, strlen(s) - 1);
reverse(s, 0 , strlen(s) - 1);
return s;
}