151. Reverse Words in a String

/*
 * 151. Reverse Words in a String
 *  Given an input string, reverse the string word by word.
For example,
Given s = "the sky is blue",
return "blue is sky the".

Update (2015-02-12):
For C programmers: Try to solve it in-place in O(1) space.
 Clarification:
What constitutes a word?
A sequence of non-space characters constitutes a word.
Could the input string contain leading or trailing spaces?
Yes. However, your reversed string should not contain leading or trailing spaces.
How about multiple spaces between two words?
Reduce them to a single space in the reversed string.

 Thinking:
  1. 先翻转整个字符,然后按单个字符翻转回来。
  2. 接下来主要考虑去掉头尾空格和把中间多个空格变成一个的问题。
  由于有空格的长度始终比没有空格的长度长,只需要记住每次应该放置的位置
  和找到应该放置的单词区间,逐一放置到对应的位置。
  例如:
  ————————————————————————————————————————————————
     _____     ____    非空格
  __|    |____|        空格
——————————————————————————————————————————————————
  _ab__c_
  找到第一个单词后面的位置,记录下来,然后把单词前移,保证是单词+1个空格的格式
  例如首先应该开始防止单词的位置为start = 0, 然后往后找,找到出现单词和再出现空格的位置,
  这里是begin = 1 和end = 3,然后把s[1],s[2] 和 空格 放到开始位置,于是开始
  位置变成了start = 3,继续重复
 * */

void reverseWordsWithRange(char *s, int startPos, int length) {
    if (length > 1) {
        for (int i = 0; i < length / 2; i++) {
            char tmp = *(s + startPos + i);
            *(s + startPos + i) = *(s + startPos + length - 1 - i);
            *(s + startPos + length - 1 - i) = tmp;
        }
    }
}

//减少头尾空格,缩减中间空格到1个
void reduceSpace(char *s) {
    int startPos = 0; //每次添加应该添加到的位置

    int wordbegin = 0; //单词的开始位置,从空格到非空格开始设置,从非空格到空格或者到达末尾重置
    int wordLength = 0; //每个单词的长度,非空格的遍历过程中+1,从非空格到空格或者到达末尾重置

    int length = strlen(s);
    //从左到右顺序遍历,一旦出现波峰或者波谷则处理,最后在根据长度设置结束标志
    //波谷->波峰
//    {
//        wordbegin = i;
//        wordLength++;
//    }
    //波峰->波谷
//    {
//        wordLength = 0;
//        wordbegin = 0;
//    }

    char switchChar = ' ';
    char beforeChar = ' ';
    for (int i = 0; i < length; i++) {
        //找到下一个波谷
        char currentChar = s[i];
        //之前是空格,并且当前不等于空格,则到达波峰
        if (beforeChar == switchChar && beforeChar != currentChar) {
            wordbegin = i;
        }

        if (currentChar != switchChar) {
            wordLength++;
        }
        //之前不是空格,当前是空格,或者到达结尾, 此处要开始执行拷贝赋值流程
        if ((beforeChar != switchChar && currentChar == switchChar) ||
                (i == length -1 && currentChar != switchChar) ) {
            for (int i = 0; i < wordLength; i++) {
                s[startPos++] = s[wordbegin + i];
            }
            if (startPos < length) {
                s[startPos++] = switchChar;
            }
            wordLength = 0;
        }


        beforeChar = currentChar;
    }

    if (startPos > 1 && s[startPos - 1] == switchChar) {
        s[startPos - 1] = '\0';
    }
    if (startPos == 0 && startPos < length) {
        s[startPos] = '\0';
    }
}

void reverseWords(char *s) {
    int length = strlen(s);
    reverseWordsWithRange(s, 0, length);

    int startPos = 0;
    int endPos = 0;
    for (int i = 0; i < length; i++) {
        //找到空格或者到达末尾
        if (s[i] == ' ' || i == length - 1) {
            endPos = i;
            if (i == length - 1) {
                endPos = length;
            }
            reverseWordsWithRange(s, startPos, (endPos - startPos));
            startPos = endPos + 1;
        }
    }
    printf("%s\n", s);
    reduceSpace(s);
    printf("%s\n", s);
}

你可能感兴趣的:(151. Reverse Words in a String)