代码随想录算法训练营第八天| 344.反转字符串 、541. 反转字符串II、剑指Offer 05.替换空格 、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串

题目链接:344.反转字符串

题目虽然要求说“不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题”,但这个问题也能看出利用对半交换的方法可以快速满足题目要求。可以通过额外定义一个中间变量的方式交换,也可以通过位运算的方法交换,建议使用位运算的方式,整体代码给出如下:

void reverseString(char* s, int sSize){
    int mid = sSize / 2;
    int i = 0;
    while (i < mid) {
        s[i] ^= s[sSize - 1 - i];
        s[sSize - 1 - i] ^= s[i];
        s[i] ^= s[sSize - 1 - i];
        ++i;
    }
}

时间复杂度O(N)
空间复杂度O(1)

题目链接:541. 反转字符串II

题目可以使用双指针叫上上一题的元素交换方式进行求解,关键是边界条件的判定问题,分为三个情况,1、恰好元素个数为偶数,2、剩余字符少于K个,3、剩余字符大于等于K个,小于2K个。三个条件分别判定即可求解,代码给出如下:

void swap(char *s, char *p, int k) {
    int i = 0;
    while (i < k / 2) {
        *(p + i) ^= *(p + k - 1 - i);
        *(p + k - 1 - i) ^= *(p + i);
        *(p + i) ^= *(p + k - 1 - i);
        ++i;
    }
}

char * reverseStr(char * s, int k){
    char *p = s;
    char *q = s;
    while (*q != '\0') {
        if (((int)(q - p) == (2*k - 1))) {
            swap(s, p, k);
            p = q + 1;
        } 
        if (((int)(q - p) < k) && (*(q + 1) == '\0')) {
            swap(s, p, (int)(q - p) + 1);
            return s;
        } 
        if ((*(q + 1) == '\0')){
            swap(s, p, k);
            return s;
        }
        q++;
    }
    return s;
}

时间复杂度O(N^2)
空间复杂度O(1)

题目链接:剑指Offer.05替换空格

题目本身不难,但这一题的关键是数组最后一定要加'\0'这个细节,这在malloc返回数组的时候就要注意了,整体代码给出如下:

char* replaceSpace(char* s){
    int i = 0;
    char *p = s;
    while (*p != '\0') {
        if (*p == ' ')
            ++i;
        ++p;
    }
    char *ret = (char *)malloc(sizeof(char) * (strlen(s) + 2 * i + 1));
    char *q = ret;
    p = s;
    while (*p != '\0') {
        if (*p != ' ') {
            *(q++) = *(p++);
        } else {
            *(q++) = '%';
            *(q++) = '2';
            *(q++) = '0';
            ++p;
        }
    }
    *q = '\0';
    return ret;
}

时间复杂度O(N)
空间复杂度O(N)

题目链接:151.翻转字符串里的单词

这一题首先需要去除字符串中多余的空格,接着我们可以将整个字符串反转,接着分别对每个单词进行翻转就可以求解,代码给出如下:

void remove_space(char *s) {
    int start = 0;
    int end = strlen(s) - 1;
    int index = 0;
    while (s[start] == ' ')
        ++start;
    while (s[end] == ' ') 
        --end;
    for (int i = start; i <= end; ++i) {
        if (s[i] == ' ' && s[i + 1] == ' ')
            continue;
        s[index++] = s[i];
    }
    s[index] = '\0';
}

void swap(char *s, int left, int len) {
    int middle = len / 2;
    for (int i = left; i < (middle + left); ++i) {
        s[i] ^= s[left + len - 1 - (i - left)];
        s[left + len - 1 - (i - left)] ^= s[i];
        s[i] ^= s[left + len - 1 - (i - left)];
    }
}


void reverse(char* s, int start, int end) {
    for (int i = start, j = end; i < j; i++, j--) {
        int tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
}

char * reverseWords(char * s){
    remove_space(s);
    swap(s, 0, strlen(s));
    //reverse(s, 0, strlen(s) - 1); // 翻转整个字符串
    int i = 0;
    int j = 0;
    for (j = 0; j <= strlen(s); ++j) {
        if ((s[j] == ' ') || (s[j] == '\0')) {
            swap(s, i, j - i);
            //reverse(s, i, j-1); // 翻转单词
            i = j + 1;
        }
    }
    return s;
}

时间复杂度O(N^2)
空间复杂度O(1)

题目链接:剑指Offer58-II.左旋转字符串

这一题看到后我想到的是定义一个额外的数组,使得题目给出指针指向定义的数组,这样数组的非'\0'元素就是题目给出元素,接着将前n个复制到最后,然后返回定义数组首地址+n,这样就可以求解,代码给出如下:

char* reverseLeftWords(char* s, int n){
    char *r = (char *)malloc(sizeof(char) * (strlen(s) + n + 1));
    int i;
    for (i = 0; i < strlen(s); ++i) {
        r[i] = s[i];
    }
    for (int j = 0; j < n; ++j) {
        r[i++] = s[j];
    }
    r[i] = '\0';
    return r + n;
}

时间复杂度O(N)
空间复杂度O(N)

看完Carl老哥给出的方法,感觉到翻转元素的妙处所在,具体内容参考代码随想录

今天感觉总体来说还算简单,但写代码的时候存在不细心、容易出现数组越界的情况,希望之后更加细心,加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值