题目主要信息:
  • 将字符串大小写反转
  • 将整个字符串的所有单词位置反转
举一反三:

学会了本题的思路,你将可以解决类似的字符串问题:

BM84. 最长公共前缀

BM85. 验证IP地址

方法一:双逆转(推荐使用)

思路:

将单词位置的反转,那肯定前后都是逆序,不如我们先将整个字符串反转,这样是不是单词的位置也就随之反转了。但是单词里面的成分也反转了啊,既然如此我们再将单词里面的部分反转过来就行。

具体做法:

  • step 1:遍历字符串,遇到小写字母,转换成大写,遇到大写字母,转换成小写,遇到空格正常不变。
  • step 2:第一次反转整个字符串,这样基本的单词逆序就有了,但是每个单词的字符也是逆的。
  • step 3:再次遍历字符串,以每个空间为界,将每个单词反转回正常。

图示:

alt

Java代码实现:

import java.util.*;
public class Solution {
    public String trans(String s, int n) {
        if(n==0) 
            return s;
        StringBuffer res=new StringBuffer();
        for(int i = 0; i < n; i++){
            //大小写转换
            if(s.charAt(i) <= 'Z' && s.charAt(i) >= 'A')   
                res.append((char)(s.charAt(i) - 'A' + 'a'));
            else if(s.charAt(i) >= 'a' && s.charAt(i) <= 'z') 
                res.append((char)(s.charAt(i) - 'a' + 'A'));
            else 
                //空格直接复制
                res.append(s.charAt(i));  
        } 
        //翻转整个字符串
        res = res.reverse();
        for (int i = 0; i < n; i++){
            int j = i;
            //以空格为界,二次翻转
            while(j < n && res.charAt(j) != ' ')  
                j++;
            String temp = res.substring(i,j);
            StringBuffer buffer = new StringBuffer(temp);
            temp = buffer.reverse().toString();
            res.replace(i,j,temp);
            i = j;
        }
        return res.toString();
    }
}

C++代码实现:

class Solution {
public:
    string trans(string s, int n) {
        if(n==0) 
            return s;
        string res;
        for(int i = 0; i < n; i++){
            //大小写转换
            if (s[i] <= 'Z' && s[i] >= 'A')   
                res += s[i] - 'A' + 'a';
            else if(s[i] >= 'a' && s[i] <= 'z') 
                res += s[i] - 'a' + 'A';
            else 
                //空格直接复制
                res+=s[i];  
        } 
        //翻转整个字符串
        reverse(res.begin(), res.end());  
        for (int i = 0; i < n; i++){
            int j = i;
            //以空格为界,二次翻转
            while(j < n && res[j] != ' ')  
                j++;
            reverse(res.begin() + i, res.begin() + j); 
            i = j;
        }
        return res;
    }
};

Python实现代码:

class Solution:
    def trans(self , s: str, n: int) -> str:
        if n==0:
            return s
        res = ""
        for i in range(n):
            #大小写转换
            if s[i] <= 'Z' and s[i] >= 'A':  
                res += chr(ord(s[i]) - ord('A') + ord('a'))
            elif s[i] >= 'a' and s[i] <= 'z':
                res += chr(ord(s[i]) - ord('a') + ord('A'))
            else :
                #空格直接复制
                res+=s[i]  
        #单词反序
        res = list(res.split(' '))[::-1]
        print(res)
        return ' '.join(res)

复杂度分析:

  • 时间复杂度:O(n)O(n),虽有多个循环,但是每个循环都只有一层O(n)O(n)
  • 空间复杂度:O(n)O(n),res是存储变换的临时字符串,也可以直接用s直接变换,这样就为O(1)O(1)
方法二:分割字符串+栈(扩展思路)

知识点:栈

栈是一种仅支持在表尾进行插入和删除操作的线性表,这一端被称为栈顶,另一端被称为栈底。元素入栈指的是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;元素出栈指的是从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

思路:

题目要求将单词逆序,逆序我们就可以想到先进后出的栈,单词之间分开逆序我们需要整个字符串分割。

具体做法:

  • step 1:遍历字符串,遇到小写字母,转换成大写,遇到大写字母,转换成小写,遇到空格正常不变。
  • step 2:按照空格把字符串分割成一个个单词.
  • step 3:遍历分割好的单词,将单词依次存入栈中。
  • step 4:再从栈中弹出单词,拼接成字符串。

图示:

图片说明

java代码实现:

import java.util.*;
public class Solution {
    public String trans(String s, int n) {
        if(n==0) 
            return s;
        StringBuffer res=new StringBuffer();
        for (int i = 0; i < n; i++){
            //大小写转换
            if(s.charAt(i) <= 'Z' && s.charAt(i) >= 'A')   
                res.append((char)(s.charAt(i) - 'A' + 'a'));
            else if(s.charAt(i) >= 'a' && s.charAt(i) <= 'z') 
                res.append((char)(s.charAt(i) - 'a' + 'A'));
             else 
                //空格直接复制
                res.append((char)(s.charAt(i)));  
        }
        Stack<String> temp=new Stack<String>();
        for (int i = 0; i < n; i++){
            int j = i;
            //以空格为界,分割单词
            while(j < n && res.charAt(j) != ' ')  
                j++;
            //单词进栈
            temp.push((String)(res.substring(i, j)));  
            i = j;
        }
        //排除结尾空格的特殊情况
        if(s.charAt(n - 1) == ' ')  
            res = new StringBuffer(" ");
        else
            res = new StringBuffer();
        //栈遵循先进后厨,单词顺序是反的
        while(!temp.empty()){   
            res.append(temp.peek());
            temp.pop();
            if(!temp.empty())
                res.append(" ");
        }
        return res.toString();
    }
}

C++代码实现:

class Solution {
public:
    string trans(string s, int n) {
        if(n==0) 
            return s;
        string res;
        for (int i = 0; i < n; i++){
            //大小写转换
            if(s[i] <= 'Z' && s[i] >= 'A')   
                res += s[i] - 'A' + 'a';
            else if(s[i] >= 'a' && s[i] <= 'z') 
                res += s[i] - 'a' + 'A';
            else 
                //空格直接复制
                res+=s[i];  
        }
        stack<string> temp;
        for (int i = 0; i < n; i++){
            int j = i;
            //以空格为界,分割单词
            while(j < n && res[j] != ' ')  
                j++;
            //单词进栈
            temp.push(res.substr(i, j - i));  
            i = j;
        }
        //排除结尾空格的特殊情况
        if(s[n - 1] == ' ')  
            res = " ";
        else
            res = "";
        //栈遵循先进后厨,单词顺序是反的
        while(!temp.empty()){   
            res += temp.top();
            temp.pop();
            if(!temp.empty())
                res += " ";
        }
        return res;
    }
};

Python实现代码:

class Solution:
    def trans(self , s: str, n: int) -> str:
        if n==0: 
            return s
        res = str()
        for i in range(n):
            #大小写转换
            if s[i] <= 'Z' and s[i] >= 'A':   
                res += chr(ord(s[i]) - ord('A') + ord('a'))
            elif s[i] >= 'a' and s[i] <= 'z' :
                res += chr(ord(s[i]) - ord('a') + ord('A'))
            else :
                #空格直接复制
                res+=s[i] 
        temp = list()
        i = 0
        while i < n:
            j = i
            #以空格为界,分割单词
            while j < n and res[j] != ' ': 
                j += 1
            #单词进栈
            temp.append(res[i:j])  
            i = j
            i += 1
        #排除结尾空格的特殊情况  
        if s[n - 1] == ' ':  
            res = " "
        else:
            res = ""
        #栈遵循先进后厨,单词顺序是反的
        while len(temp) != 0:   
            res += temp[-1]
            temp.pop()
            if len(temp) != 0:
                res += " "
        return res

复杂度分析:

  • 时间复杂度:O(n)O(n),所有循环最多遍历一次
  • 空间复杂度:O(n)O(n),栈空间的大小最坏为O(n)O(n)