42 - 反转单词的顺序 | 左旋转字符串

1. 反转单词的顺序

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。
例如输入“I am a student.”,则输出“student. a am I”。


先反转整个句子中的字符顺序,再反转每个单词中的字符顺序;
或者先反转每个单词中的字符顺序,再反转整个句子中的字符顺序。

#include <iostream>
using namespace std;
void swap(char* p, char* q) {
    char temp = *p; *p = *q; *q = temp;
}
void Reverse(char* pBegin, char* pEnd) {
    if (pBegin == NULL || pEnd == NULL || *pBegin == '\0' || *pEnd == '\0')
        return;
    while (pBegin < pEnd) {
        swap(pBegin, pEnd);
        pBegin++, pEnd--;
    }
    return;
}
// 先反转整个句子,再反转每个单词(也可以先翻单词,再翻句子)
void ReverseSentence(char* s) {
    if (s == NULL || *s == '\0')
        return;
    char* pBegin = s;
    char* pEnd = s;
    while (*pEnd != '\0')
        pEnd++;
    pEnd = pEnd-1; // 指向最后一个非'\0'字符
    Reverse(pBegin, pEnd); // 反转整个句子
    pBegin = pEnd = s;
    while (*pBegin != '\0') {
        if (*pBegin == ' ') {
           pBegin++, pEnd++; //跳过空格
        } else if (*pEnd == ' ' || *pEnd == '\0') {
            Reverse(pBegin, pEnd-1); // 反转单词
            pBegin = pEnd;
        } else {
            pEnd++;
        }
    }
}
int main() {
    char s[] = "I am a student.";
    char s1[] = "student.";
    char s2[] = "   ";
    ReverseSentence(s);
    ReverseSentence(s1);
    ReverseSentence(s2);
    ReverseSentence(NULL);
    cout << s << endl;
    cout << s1 << endl;
    cout << s2 << endl;


}

输出:

student. a am I
student.

[Finished in 0.9s]

2. 左旋转字符串

定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部,如把字符串abcdef左旋转2位得到字符串cdefab。
请实现字符串左旋转的函数,要求对长度为n的字符串操作的时间复杂度为O(n),空间复杂度为O(1)。


由上题中的方法,abcdef 反转 2 位 可以看做 ab,cdef 的反转问题。
首先反转 ab 和 cdef ,得到 bafedc ,然后反转整个字符串,得到 cdefab.

其他更高级的算法:程序员编程艺术:第一章、左旋转字符串

#include <iostream>
using namespace std;
void swap(char* p, char* q);
void Reverse(char* pBegin, char* pEnd);
// 把 s 左旋 k 位
void LeftRotate(char* s, int k) {
    if (s == NULL || *s == '\0' || k <= 0)
        return;
    int len = 0;
    char* pBegin = s, *pEnd = s;
    // 计算字符串大小,并得到字符串尾指针
    while (*pEnd != '\0') {
        len++;
        pEnd++;
    }
    pEnd = pEnd-1;
    k = k % len;
    if (k == 0)
        return;
    char* pMiddle = pBegin + k-1;
    // 分别反转左右2部分
    Reverse(pBegin, pMiddle);
    Reverse(pMiddle+1, pEnd);
    // 反转整体
    Reverse(pBegin, pEnd);
}

void swap(char* p, char* q) {
    char temp = *p; *p = *q; *q = temp;
}
void Reverse(char* pBegin, char* pEnd) {
    if (pBegin == NULL || pEnd == NULL || *pBegin == '\0' || *pEnd == '\0')
        return;
    while (pBegin < pEnd) {
        swap(pBegin, pEnd);
        pBegin++, pEnd--;
    }
    return;
}
int main() {
    char s1[] = "abcdef";
    char s2[] = "abcdef";
    LeftRotate(s1,2);
    LeftRotate(s2,8);
    cout << s1 << endl;
    cout << s2 << endl;
}

结果:

cdefab
cdefab
[Finished in 0.8s]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值