《剑指offer》42:翻转单词顺序

来源:互联网 发布:大数据在医疗领域应用 编辑:程序博客网 时间:2024/06/07 02:43

这个单元有两道题,都是字符串操作,挺简单的,不过如果没经历过思考的过程,可能就不是那么容易了,简单 != 容易
书里安排了比较简单的左旋字符串在后面,我觉得反了,所以换了顺序来说。

左旋字符串

将一个字符串“左移”k位,比如”123456789”左移3位变成”456789123”。

最笨的方法

逐个向左移动,比如123456789->234567891->345678912->…
每次移动的时间复杂度都是O(n),总的复杂度就是O(kn),k最多可以为n-1,所以复杂度最坏可达到O(n^2)!

假设k=3,则需要把”123456789”->”456789123”。看仔细一下,其实是把字符串分成两部分,”123”和”456789”,想把它们两个交换位置而已!

两部分的长度不一样,否则就可以简单地交换了。

不妨先反转整个字符串一遍:987654321。

可以发现,两部分已经到了它们所需要到的位置了,123到了末端,456789到了开头,只不过它们现在都是反转过来了而已,只需要各自再反转一遍就可以了!!!

最后,要注意处理一下,k = k % str.size(),然后看k等于0的话,就不用处理了,原因就不多说了~应该挺明显的

#include <iostream>#include <string>using namespace std;void reverseHelper(string& str, int beg, int end) {    for (int i = beg, j = end; i < j; ++i, --j)        swap(str[i], str[j]);}void reverseWord(string& str, int k) {    int len = str.size();    k = k % len;    if (k > 0) {        reverseHelper(str, 0, k-1);        reverseHelper(str, k, len-1);        reverseHelper(str, 0, len-1);    }}int main() {    string str = "hi jacket";    reverseWord(str, 2);    cout << "Finally, str=" << str << endl;    return 0;}

翻转单词顺序

把一个句子的单词为A B C …,变为… C B A,比如”hello world”变为”world hello”,而”I am a student.”变为”student. a am I”,也就是说,标点符号跟随它前一个单词在一起。

要求:用O(1)的空间和O(n)的时间。

其实原理跟上面的是一样的,只是单词的数量多了,需要用空格将彼此区分开而已~

#include <iostream>#include <string>using namespace std;void reverseHelper(string& str, int beg, int end) {    for (int i = beg, j = end; i < j; ++i, --j)        swap(str[i], str[j]);}void reverseSentence(string& str) {    int len = str.size(), i = -1, last = 0;    reverseHelper(str, 0, len-1);    while (++i <= len) {        // 这是我目前能想到的最优美的写法了!!!        if (i == len || str[i] == ' ') {            reverseHelper(str, last, i-1);            last = i + 1;        }    }}int main() {    string str = "I am a student.";    reverseSentence(str);    cout << "Finally, str=" << str << endl;    return 0;}
1 0
原创粉丝点击