leetcode-151:翻转字符串里的单词

简介: leetcode-151:翻转字符串里的单词

题目

题目链接

给定一个字符串,逐个翻转字符串中的每个单词。

示例 1:

输入:"the sky is blue"
输出:"blue is sky the"

示例 2:

输入:"  hello world!  "
输出:"world! hello"
解释:输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:

输入:"a good   example"
输出:"example good a"
解释:如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

示例 4:

输入:s = "  Bob    Loves  Alice   "
输出:"Alice Loves Bob"

示例 5:

输入:s = "Alice does not even like bob"
输出:"bob like even not does Alice"

解题

方法一:使用语言特性

很多语言对字符串提供了 split(拆分),reverse(翻转)和 join(连接)等方法,因此我们可以简单的调用内置的 API 完成操作:

class Solution:
    def reverseWords(self, s: str) -> str:
        return " ".join(reversed(s.split()))

注意

这样子是不行的,因为这样只是以空格split,但是如果单词之间出现2个空格,就没有办法了。

split()默认是以空格、退格、回车等作为分隔.

return " ".join(reversed(s.split(" ")))

方法二:双端队列

class Solution:
    def reverseWords(self, s: str) -> str:
        left, right = 0, len(s) - 1
        # 去掉字符串开头的空白字符
        while left <= right and s[left] == ' ':
            left += 1
        # 去掉字符串末尾的空白字符
        while left <= right and s[right] == ' ':
            right -= 1
        d, word = collections.deque(), []
        # 将单词 push 到队列的头部
        while left <= right: # 一定要取等号,不然最后一个字符取不到
            if s[left] == ' ' and word:
                d.appendleft(''.join(word))
                word = []
            elif s[left] != ' ':
                word.append(s[left])
            left += 1
        d.appendleft(''.join(word))
        return ' '.join(d)

方法三:c++解法1

class Solution {
public:
    string reverseWords(string s) {
        int len = s.length(), i = 0;
        string ans = "", tmp;
        while(i < len){
            tmp = "";
            while(i < len && s[i] == ' ') i++;
            while(i < len && s[i] != ' ') tmp += s[i++];
            if(tmp != ""){ //防止s末尾的空格
                ans = tmp + " " + ans;
            }
        }
        return ans.substr(0, ans.length()-1);
    }
};

substr相当于python中对字符串的切片

最后ans.substr(0, ans.length()-1);是为了舍弃字符串最后一个字符

因为刚开始进入ans = tmp + " " + ans;时候,ans="",直接 tmp+空格,所以末尾会多一个空格,最后return的时候空格是出现在最末尾.

方法四:c++解法2

class Solution {
public:
    // 反转字符串s中左闭又闭的区间[start, end]
    void reverse(string& s, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            swap(s[i], s[j]);
        }
    }
    // 移除冗余空格:使用双指针(快慢指针法)O(n)的算法
    void removeExtraSpaces(string& s) {
        int slowIndex = 0, fastIndex = 0; // 定义快指针,慢指针
        // 去掉字符串前面的空格
        while (s.size() > 0 && fastIndex < s.size() && s[fastIndex] == ' ') {
            fastIndex++;
        }
        for (; fastIndex < s.size(); fastIndex++) {
            // 去掉字符串中间部分的冗余空格
            if (fastIndex - 1 > 0
                    && s[fastIndex - 1] == s[fastIndex]
                    && s[fastIndex] == ' ') {
                continue;
            } else {
                s[slowIndex++] = s[fastIndex];
            }
        }
        if (slowIndex - 1 > 0 && s[slowIndex - 1] == ' ') { // 去掉字符串末尾的空格
            s.resize(slowIndex - 1);
        } else {
            s.resize(slowIndex); // 重新设置字符串大小
        }
    }
    string reverseWords(string s) {
        removeExtraSpaces(s); // 去掉冗余空格
        reverse(s, 0, s.size() - 1); // 将字符串全部反转
        int start = 0; // 反转的单词在字符串里起始位置
        int end = 0; // 反转的单词在字符串里终止位置
        bool entry = false; // 标记枚举字符串的过程中是否已经进入了单词区间
        for (int i = 0; i < s.size(); i++) { // 开始反转单词
            if (!entry) {
                start = i; // 确定单词起始位置
                entry = true; // 进入单词区间
            }
            // 单词后面有空格的情况,空格就是分词符
            if (entry && s[i] == ' ' && s[i - 1] != ' ') {
                end = i - 1; // 确定单词终止位置
                entry = false; // 结束单词区间
                reverse(s, start, end);
            }
            // 最后一个结尾单词之后没有空格的情况
            if (entry && (i == (s.size() - 1)) && s[i] != ' ' ) {
                end = i;// 确定单词终止位置
                entry = false; // 结束单词区间
                reverse(s, start, end);
            }
        }
        return s;
    }
    // 当然这里的主函数reverseWords写的有一些冗余的,可以精简一些,精简之后的主函数为:
    /* 主函数简单写法
    string reverseWords(string s) {
        removeExtraSpaces(s);
        reverse(s, 0, s.size() - 1);
        for(int i = 0; i < s.size(); i++) {
            int j = i;
            // 查找单词间的空格,翻转单词
            while(j < s.size() && s[j] != ' ') j++;
            reverse(s, i, j - 1);
            i = j;
        }
        return s;
    }
    */
};

方法五:c++解法3

class Solution {
public:
    string reverseWords(string s) {
        int n=s.size();
        int left=0;
        int right=n-1;
        while(left<n&&s[left]==' ') left++;
        while(right>=0&&s[right]==' ') right--;
        string res="";
        while(right>=left){
            int start=right;
            while(right>=left&&s[right]!=' ') right--;
            res+=s.substr(right+1,start-right);
            while(right>=left&&s[right]==' ') right--;
            if(right!=left-1){
                res+=" ";
            }
        }
        return res;
    }
};

java

class Solution {
    public String reverseWords(String s) {
        int n=s.length();
        StringBuilder res=new StringBuilder();
        //两边去掉空格
        int left=0,right=n-1;
        while(right>=0&&s.charAt(right)==' ') right--;
        while(left<n&&s.charAt(left)==' ') left++;
        while(left<=right){
            int start=right;
            while(right>=left&&s.charAt(right)!=' ') right--;
            res.append(s.substring(right+1,start+1));
            while(right>=left&&s.charAt(right)==' ')right--;//跳过空格
            if(right!=left-1){
                res.append(' ');
            }
        }
        return res.toString();
    }

或者使用java提供的一些函数

class Solution {
    public String reverseWords(String s) {
        String[] str=s.split(" ");
        StringBuilder sb=new StringBuilder();
        int state=0;
        for(int i=str.length-1;i>=0;i--){
            if(!str[i].equals("")){//注意是空的,因为连续两个空格split的话,"  "得到结果为{"","",""}
                sb.append(str[i]);
                sb.append(" ");
            }
        }
        return sb.toString().trim();
    }
}
相关文章
|
2天前
|
Go C++
【力扣】2696. 删除子串后的字符串最小长度(模拟 栈 C++ Go实现栈)
【2月更文挑战第18天】2696. 删除子串后的字符串最小长度(模拟 栈 C++ Go实现栈)
35 6
|
2天前
|
存储
力扣面试经典题之数组/字符串
力扣面试经典题之数组/字符串
26 0
|
2天前
|
存储 算法 安全
【刷题】 leetcode 面试题 01.06 字符串压缩
来看效果: 非常好!!!过啦!!!
25 5
【刷题】 leetcode 面试题 01.06 字符串压缩
|
2天前
leetcode代码记录(删除字符串中的所有相邻重复项
leetcode代码记录(删除字符串中的所有相邻重复项
11 0
|
2天前
|
算法
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
代码随想录算法训练营第五十五天 | LeetCode 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
24 1
|
2天前
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
|
2天前
|
机器学习/深度学习 索引
【力扣】387. 字符串中的第一个唯一字符
【力扣】387. 字符串中的第一个唯一字符
|
2天前
|
存储
leetcode2744. 最大字符串配对数目
leetcode2744. 最大字符串配对数目
17 0
|
2天前
|
机器学习/深度学习 NoSQL Shell
力扣刷题-翻转字符串
力扣刷题-翻转字符串
12 1