代码随想录算法训练营Day8

117 阅读5分钟

代码随想录算法训练营Day8

344.反转字符串

思路

和数组反转基本一致,用两个指针分别从头尾开始交换所指元素并且相向移动直到相遇为止。

代码实现

void reverseString(char* s, int sSize) {
    if(sSize <= 0){
        return;
    }
    int left = 0;                           //左指针
    int right = sSize - 1;                  //右指针
    //当sSize为偶数时,最后一次交换结束后left == right+1;当sSize为奇数时,最后一次交换结束后left == right
    //因此结束循环条件为left < sSize
    while (left < right) {
        char temp = s[right];
        s[right] = s[left];
        s[left] = temp;
        left++;
        right--;
    }
}

image-20240108111540208

代码实现

void reverseString2(char* s, int start, int end) {
    if(start > end){
        return;
    }
    int left = start;                           //左指针
    int right = end;                            //右指针
    //因此结束循环条件为left < sSize
    while (left < right) {
        char temp = s[right];
        s[right] = s[left];
        s[left] = temp;
        left++;
        right--;
    }
}

char* reverseStr(char* s, int k) {
    char* str = s;
    long length = strlen(s);                                    //字符串长度
    long times = length / (2 * k);                              //最多能达到几次2k
    long remain = length % (2 * k);                             //最后不满2k的数据长度
    for (int i = 0; i < times; i++) {
        //没遇到2k个长度的子串,反转前k个字符
        reverseString2(s, i * 2 * k, i * 2 * k + k - 1);
    }
    if(remain < k){
        //剩余字符长度小于k,则全部反转
        reverseString2(s, times * 2 * k, times * 2 * k + remain - 1);
    }else{
        //否则反转前k和字符
        reverseString2(s, times * 2 * k, times * 2 * k + k - 1);
    }
    return str;
}

image-20240108153634607

54.替换数字

思路

如果是实现返回字符串的函数:

  1. 统计原字符串中的数字字符个数,数字字符用'0' <= ch <='9'来限定
  2. 根据统计的数字字符个数申请出合适的最终结果的合适空间
  3. 重新遍历原字符串,遇到非数字字符则填入原字符;遇到数字字符则填入number

如果是直接打印目标结果:

  1. 遍历原数组,如果遇到非数字字符,则直接打印本身
  2. 如果遇到数字字符,则打印number

代码实现

#include<stdio.h>

char s[]= "number";
int main(int argc, const char * argv[]) {
    char str[10001] = {'\0'};
    scanf("%s",str);
    for(int i = 0; str[i] != '\0'; i++){
        //如果是数字字符,则按顺序打印number
        if(str[i] >= '0' && str[i] <= '9'){
            // 打印number
            printf("%s",s);
        } else{
            //如果是非数字字符,则直接打印这个字符
            printf("%c", str[i]);
        }
    }
    printf("\n");
    return 0;
}

image-20240109001558037

151.翻转字符串里的单词

思路

  1. 字符串周围边缘可能会有多余空格,需要移除
  2. 除去多余空格之后将整个字符串翻转
  3. 依次翻转单词,即可实现效果。

代码实现

void reverseString2(char* s, int start, int end) {
    if(start > end){
        return;
    }
    int left = start;                           //左指针
    int right = end;                            //右指针
    //因此结束循环条件为left < sSize
    while (left < right) {
        char temp = s[right];
        s[right] = s[left];
        s[left] = temp;
        left++;
        right--;
    }
}

void removeExtraSpaces(char *s){
    // 字符串长度
    long length = strlen(s);
    if(length <= 0){
        return;
    }
    // 去除多余空格后的位置指示
    int position = 0;
    // 遍历用的探针
    int probe = 0;
    // 先跳过字符串前方的字符
    while (probe < length && s[probe] == ' ') {
        probe++;
    }
    // 如果已经走到头,说明全是空格,直接补上结束符
    if(probe == length){
        s[position] = '\0';
        return;
    }
    while (probe < length) {
        // 如果遇到非空格字符,则填入对应的位置,并且向后移动
        if(s[probe] != ' '){
            s[position] = s[probe];
            position++;
            probe++;
        }else{
            // 第一个空格可以保留
            s[position] = s[probe];
            position++;
            probe++;
            // 跳过除了第一个空格以外的所有空格
            while (probe < length && s[probe] == ' ') {
                probe++;
            }
        }
    }
    //处理结束后,如果原字符串结尾本身带有空格,则会多一个空格在结尾,需要特殊处理。
    if(position > 0 && s[position - 1] == ' '){
        // 补充一个结尾
        s[position - 1] = '\0';
    }else{
        s[position] = '\0';
    }
}

char* reverseWords(char* s) {
    int start = 0;
    int end  = 0;
    removeExtraSpaces(s);
    //要取去除空格后的长度,否则会出错
    long length = strlen(s);
    reverseString2(s, 0, (int)length - 1);
    while (s[end] != '\0') {
        // 如果遇到一个空格,说明之前已经到了一个词的结尾处
        if(s[end] == ' '){
            // 当前end在空格上,则单词结尾为end - 1
            reverseString2(s, start, end - 1);
            // 显然如果有下一个单词,则位置是end的下一个位置
            start =  end + 1;
        }
        end++;
    }
    // 跳出循环说明走到最后一个单词了
    reverseString2(s, start, end - 1);
    return s;
}

image-20240109231059113

55.右旋字符串

思路

假设字符串从头到尾的字符为c0、c1、c2...cn-1,如果要右旋k位,则会变为:

cn-k、cn-k+1、cn-k+2...cn-1、c0、c1、c2...cn-k-1.

如果直接翻转字符串,则会得到:

cn-1、cn-2、cn-3...cn-k、cn-k-1...c3、c2、c1、c0

再对此时的前k个字符进行翻转则可以得到:

cn-k、cn-k+1、cn-k+2...cn-1、cn-k-1...c3、c2、c1、c0

再对后n-k个字符进行翻转则为

cn-k、cn-k+1、cn-k+2...cn-1、c0、c1、c2、c3、cn-k-1

发现和目标一致,因此翻转k位就可以按照这个思路来处理

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void reverseString2(char* s, int start, int end) ;
int main(int argc, const char * argv[]) {
    char str[10001] = {'\0'};
    int k = 0;
    scanf("%d %s",&k,str);
    long length = strlen(str);
    // 整体翻转
    reverseString2(str, 0, length - 1);
    // 翻转前k位
    reverseString2(str, 0, k - 1);
    // 翻转后n-k位
    reverseString2(str, k, length - 1);
    printf("%s",str);
    printf("\n");
    return 0;
}

void reverseString2(char* s, int start, int end) {
    if(start > end){
        return;
    }
    int left = start;                           //左指针
    int right = end;                            //右指针
    //因此结束循环条件为left < sSize
    while (left < right) {
        char temp = s[right];
        s[right] = s[left];
        s[left] = temp;
        left++;
        right--;
    }
}

image-20240109014734199