代码随想录第八天 | 344.反转字符串 、 541. 反转字符串II、 卡码网:54.替换数字 、 151.翻转字符串里的单词 、卡码网:55.右旋转字符串

今天的主题是字符串,题目一共有五个,还可以。参考资料:卡哥文献

一、反转字符串:

1、思路:

这一道题我没有多想,第一秒就是想到的是双指针:

(1)一个指针指头,一个指针指向尾部

(2)把指针放到循环中去遍历和交换即可了。

2、代码:

(1)自己写的版本:

    void reverseString(vector<char>& s) {
        char temp;
        int tail = s.size() - 1;
        for (int head = 0; head < tail; head++) {
            temp = s[head];
            s[head] = s[tail];
            s[tail] = temp;
            tail--;
        }
    }

时间复杂度是O(n),空间复杂度是O(1),符合题目要求,但是感觉不是很快,我参考了以下卡哥的方法,卡哥的思路和我一样,但是他的方法调用了一个交换的库函数。

(2)卡哥版本:

class Solution {
public:
    void reverseString(vector<char>& s) {
        // char temp;
        int tail = s.size() - 1;
        for (int head = 0; head < tail; head++) {
            // temp = s[head];
            // s[head] = s[tail];
            // s[tail] = temp;
            swap(s[head], s[tail]);
            tail--;
        }
    }
};

二、反转字符串||

看完题目,就想着用双指针,结果写出来一个bug多多的程序。。

1、错误代码:

    string reverseStr(string s, int k) {
        if (s.size() < k) {
            reverse(s.begin(), s.end());
            return s;
        }
        int tail = 0;
        int head = 0;
        for (; head < s.size(); head++) {
            if ((head + 1) / k == 2) {
                int temp = head;
                head = head / 2;
                while (head > tail) {
                    swap(s[head], s[tail]);
                    head--;
                    tail++;
                }
                tail = temp + 1;
                head = temp + 1;
            }
        }
        if (head - tail >= k) {
            head = tail + k - 1;
            while (head > tail) {
                    swap(s[head], s[tail]);
                    head--;
                    tail++;
                }
        } else {
                while (head > tail) {
                    swap(s[head], s[tail]);
                    head--;
                    tail++;
                }
        }
        return s;
    }

这个代码总是缝缝补补,一直运行不出来

请求了以下GPT教授,帮我改了一下代码,GPT教授太厉害了。

2、修正后代码:

    string reverseStr(string s, int k) {
        int n = s.size();
        for (int i = 0; i < n; i += 2 * k) {
            int head = i;
            int tail = min(i + k - 1, n - 1);
            while (tail > head) {
                swap(s[head], s[tail]);
                tail--;
                head++;
            }
        }
        return s;
    }

这里利用了一个很巧妙的tail的取值方法,tail = i+k-1 和 n-1中的较小的一个,这样就可以很方便的判断那个时候到了tail 与 head的差距小于k了,就只需要变动tail的值就可以解决了。

看完卡哥的代码之后,就发现和gpt教授的思路差不多,都是在for循环上面做文章

3、卡哥代码:

    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += 2 * k) {
            if (i + k < s.size()) {
                reverse(s.begin() + i, s.begin() + i + k);
            } else {
                reverse(s.begin() + i, s.end());
            }
        }
        return s;
    }

卡哥的反转是利用了库函数的,所以看起来更加的简洁;

三、替换数字

卡哥的网站的题目,有点懵逼,虽然理解题意,但是对c++的数据结构还是不是很清楚,只好看看题解了。

看完之后发现也没有那么离谱,但是这个思想确实值得学习,这就是从后向前开始更替,代码如下

1、代码:

#include<iostream>
using namespace std;
int main() {
    string s;
    while (cin >> s) {
        int count = 0; // 统计数字的个数
        int sOldSize = s.size();
        for (int i = 0; i < s.size(); i++) {
            if (s[i] >= '0' && s[i] <= '9') {
                count++;
            }
        }
        // 扩充字符串s的大小,也就是每个空格替换成"number"之后的大小
        s.resize(s.size() + count * 5);
        int sNewSize = s.size();
        // 从后先前将空格替换为"number"
        // 都是从最后开始
        // 不是数字就往后移
        // 是数字就变为number
        for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
            if (s[j] > '9' || s[j] < '0') {
                s[i] = s[j];
            } else {
                s[i] = 'r';
                s[i - 1] = 'e';
                s[i - 2] = 'b';
                s[i - 3] = 'm';
                s[i - 4] = 'u';
                s[i - 5] = 'n';
                //  更新i的数值
                i -= 5;
            }
        }
        cout << s << endl;
    }
}

照着卡哥的代码写了一遍,感觉是有收获的。

四、反转字符串中的单词

1、思路:

(1)去掉多余的空格

(2)第一步把所有字符串反转

(3)在逐个单词反转

总体来说就这三个函数,实现出来就好了

2、代码:

    void reverseStr(string& s, int left, int right) {
        while (left < right) {
            swap(s[left], s[right]);
            left++;
            right--;
        }
    }

    void DeleteBlank(string& s) {
        int fast = 0;
        int slow = 0;
        while (s[fast] == ' ' && fast < s.size()) {
            fast++;
        }
        for (; fast < s.size(); fast++) {
            if (fast - 1 > 0 && s[fast] == ' ' && s[fast - 1] == ' ') {
                continue;
            }
            else {
                s[slow++] = s[fast];
            }
        }
        if (slow - 1 > 0 && s[slow - 1] == ' ') {
            s.resize(slow - 1);
        }
        else {
            s.resize(slow);
        }
    }


    string reverseWords(string& s) {
        DeleteBlank(s);
        reverseStr(s, 0, s.size() - 1);
        int slow = 0;
        for (int fast = 0; fast <= s.size(); fast++) {
            if (s[fast] == ' ' || fast == s.size()) {
                reverseStr(s, slow, fast - 1);
                slow = fast + 1;
            }

        }
        return s;
    }

先总体,再局部。

五、右旋字符串

1、思路:

先总体,再局部

2、代码:

#include<iostream>
using namespace std;

void reverse(string &s, int left, int right) {
    while (left < right) {
        swap(s[left], s[right]);
        left++;
        right--;
    }
}

int main() {
    
    string s;
    int k;
    cin >> k;
    cin >> s;

    
    reverse(s, 0, s.size() - 1);
    reverse(s, 0, k - 1);
    reverse(s, k, s.size() - 1);
    
    cout << s << endl;
    
    
    return 0;
}

调试了几波,终于过了哈哈哈,明天继续努力!

学习时长两个半小时!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值