翻转字符串里的单词(4种解法)

力扣151:翻转字符串里的单词

题目描述:
给定一个字符串,逐个翻转字符串中的每个单词。

说明:
无空格字符构成一个 单词 。
输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

示例 1:
输入:“the sky is blue”
输出:“blue is sky the”
示例 4:
输入:s = " Bob Loves Alice "
输出:“Alice Loves Bob”

这道题目用了四种不同的解法,每种解法都有自己的独到之处。

解法一
解释

//方法一
class Solution {
    public String reverseWords(String s) {
        s = s.trim();
        StringBuilder sb = new StringBuilder();
        char[] charArray = s.toCharArray();
        int len = charArray.length;

        //获取一个单词word
        for(int i = len-1;i >= 0;){
            StringBuilder word = new StringBuilder("");//初始化为空字符串便于统计下一个单词

            //处理到第一个字符时,不再减了,否则越界;试了单独判断当i=-1时即break;最后想到直接把两个条件顺序变了就可以了,因为先判断i>=0,若不符合=-1时,便不再判断后面的为空条件(与的特性),就完美解决了问题while(charArray[i] != ' ' && i>=0),这样就不行,到第一个字符时会数组越界
            while(i >= 0 && charArray[i] != ' '){
                word.append(charArray[i]);
                i--;     
            }
            word.reverse();//得到单词的反序,将其反转得到单词
            sb.append(word);//将该单词添加到sb中
            //最后一个单词结束时不应该有空格
            if(i != -1)
                sb.append(' ');
            
            //碰到空格了(可能是多个空格),则利用循环,碰到空格时不管遍历下一个
            while(i > 0 && charArray[i] == ' '){
                i--; 
            }
        }
        return sb.toString();
    }
}
//时间:80%O(N);空间:O(N)30%

解法二:

class Solution{
    public String reverseWords(String s) {
        s = s.trim();//去掉首尾端空格
        //先用支持正则化的split将含有多个空格的字符串分割成字符串数组,因为字符串数组没有反转功能,再将字符串数组转成字符串列表
        List<String> wordList = Arrays.asList(s.split("\\s+"));
        //反转列表,Collections类中很多都是静态方法,所以类直接调用。Collections.reverse(list)
        Collections.reverse(wordList);
        //将反转后列表中的单词拼接起来,用join,用法? 
        //用String方法中新增的方法join(String link, String[] arr),用连接符将字符串数组中的每个字符串连接起来
        return String.join(" ", wordList);
    }
}
//时间:22%,空间:28%

解法三:

/*方法三:
class Solution{
    public String reverseWords(String s) {
        s = s.trim();
        String[] wordArray = s.split("\\s+");//也可以用substring截取每个单词
        int len = wordArray.length;
        StringBuilder sb = new StringBuilder();
        for(int i = len - 1;i >= 0;i --){
            sb.append(wordArray[i]);
            if(i != 0){
                sb.append(" ");
            }
        }
        return sb.toString();
    }
}
//时间:13%,空间:46%

解法四:

/*方法四:空间O(1) 时间:5%,空间:74%
class Solution{
    public String reverseWords(String s) {
        //先将整个字符串反转
        s = s.trim();
        int len = s.length();
        //new StringBuilder(s).reverse();这样不对,因为s还是String类型,而且String是不可变的,那么O(1)怎么理解???
        StringBuilder sb = new StringBuilder(s).reverse();
        System.out.println(sb);
        //将每个单词反转
        for(int i = 0; i < sb.length();){
            //找出一个单词
            int start = i;
            len = sb.length();
            while(i < len && sb.charAt(i) != ' '){
                i++;
            }//i=len
            System.out.println(i);
            int end = i-1;
            if(i < len){
                int j = i + 1;//保留一个空格i处
                //删除多个空格
                while(i < len && sb.charAt(i) == ' '){
                    i++;
                }
                System.out.println(i + "===" + sb.charAt(i));
                sb.delete(j,i);//左闭右开
                i -= i - j; // 因为你删除了两个空格,字符串的长度随着改变,那么原来指向 d 的 i,不在指向 d
                //反转单词
                reverseWord(sb,start,end);
            }
            else{
                reverseWord(sb,start,end);
            }
        }
        return sb.toString();
    }

    public void reverseWord(StringBuilder sb, int start, int end){//左闭右闭
        System.out.println(start + "   " + end);
        for(int i = start,j = end;i <= j;i++,j--){
            char tmp = sb.charAt(i);//charAt(i)注意是圆括号,不是方括号
            sb.setCharAt(i, sb.charAt(j));
            sb.setCharAt(j, tmp);
        }
    }
}

解法五:

/*空间为O(1)的题解
class Solution {
    public String reverseWords(String s) {
        if(s==null || (s=s.trim()).isEmpty()) return "";
        int i,j,start,end;
        //首先翻转trim()后的一大长条字符串,之后再翻转每个单词(String内定义的char[]用final修饰,不可再变)
        StringBuilder sentence=new StringBuilder(s).reverse();
        //用来记录一个单词的前后两个空格
        start=end=0;
        for(i=0;i<sentence.length();i++){
            //如果碰到了一个空格,说明这个空格前到之前的一个空格已经有一个单词了,现在要翻转这个单词了
            if(sentence.charAt(i)==' '){
                //单词之间只能有一个空格,删除多余空格
                j=i+1;
                while(sentence.charAt(j)==' '){
                    j++;
                }
                //delete方法前 包括,后 不包括
                sentence.delete(i+1,j);
                //翻转单个单词
                end=i-1;
                revSingleWord(sentence,start,end);
                //重新确定下一个单词的起始位置
                start=i+1;
            }
        }
        //由于最后一个单词末尾没有空格,所以这里多处理一下
        revSingleWord(sentence,start,i-1);
        return sentence.toString();
    }
 
     //翻转单个单词
    public void revSingleWord(StringBuilder sentence,int start,int end){
        while(start<end){
            char temp=sentence.charAt(start);
            sentence.setCharAt(start++,sentence.charAt(end));
            sentence.setCharAt(end--,temp);
        }
    }
}
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值