Day 8 151. 反转字符串中的单词 卡码网55. 右旋字符串(第八期模拟笔试)

43 阅读3分钟

151. 反转字符串中的单词 - 力扣(LeetCode)

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意: 输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。不能使用额外的空间。

思路难点: 如果不使用额外的空间,就需要整体翻转+局部翻转

编程难点: 去除多余空格的函数实现,确保逻辑清晰

注意点:

  1. void removeExtraSpace(string& s),因为要修改s本身,一定要传引用,没有&号,只会传入一份copy并对copy进行后续操作,不会真正修改s
  2. s.resize(slow);去除多余空格后,记得resize截断
  3. removeExtraSpace(s); int size = s.size();去除多余空格后,size发生变化,别忘了
class Solution {
public:
    void reverse(string& s,int start,int end){  //翻转函数
        char temp;
        while(start < end){
            temp = s[start];
            s[start] = s[end];
            s[end] = temp;
            start++;
            end--;
        }
    }

    void removeExtraSpace(string& s){ //传引用!
        int size = s.size();
        int fast = 0;
        int slow = 0;
        while(fast < size){
            if(s[fast]!=' '){//开始遇到字符,也就是新的单词
                if(slow != 0) s[slow++] = ' ';//如果不是开头,补上单词前的空格
                //该while会遍历完整个单词
                while(s[fast]!=' '&& fast < size){
                    s[slow] = s[fast];
                    slow++;
                    fast++;
                }
                //出while时,已经处理完完整的单词,且遇到了空格或者已经结束        
            }
            else fast++;
        }
        s.resize(slow);
    }

    string reverseWords(string s) {
        removeExtraSpace(s);
        int size = s.size();
        reverse(s,0,size-1);
        int start = 0;
        for(int i = 0;i<size;i++){
            if(s[i]==' '){   //遇到空格,说明一个单词结束
                reverse(s,start,i-1);
                start = i + 1;
            }
            else if(i == size-1){  //走到结尾了
                reverse(s,start,i);
            }
        }
        return s;
    }
};

55. 右旋字符串(第八期模拟笔试)

字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串s和一个正整数k,请编写一个函数,将字符串中的后面k个字符移到字符串的前面,实现字符串的右旋转操作。 

例如,对于输入字符串"abcdefg"和整数2,函数应该将其转换为"fgabcde"不能使用额外的空间。

如果使用额外空间,先记录后k个字符为一个新的字符串,再把前面的元素向后移,注意要从后往前遍历,避免从前往后遍历时多次搬移元素。再把新的字符串写入前k位即可。

不使用额外空间的方法很巧妙:

Step1: 将字符串整个反转。"abcdefg"→"gfedcba",完成这一步后,发现"gf | edcba"前后两部分的元素是符合要求的,但顺序不对。

Step2: 分别对两个子串进行翻转。翻转前k个元素得到:"fg | edcba";翻转后size-k个元素得到:"fg | abcde";最终结果为"fgabcde"

#include<iostream>
#include<string>
//翻转函数
void reverse(std::string& s,int start,int end){
    char temp;
    while(start<end){
        temp = s[start];
        s[start] = s[end];
        s[end] = temp;
        start++;
        end--;
    }
}
int main(){
    int k;   //要处理后k个字符
    std::cin >> k;  
    std::string s;    //待处理的字符串
    std::cin >> s;

    reverse(s,0,s.size()-1);  //整体反转

    reverse(s,0,k-1);         //反转前k个元素

    reverse(s,k,s.size()-1);  //反转后size-k个元素
    std::cout<<s<<std::endl;
    return 0;
}

kmp

要不二刷再说 ^_^