[Leetcode学习-java]Reverse Words in a String(将字符串单词顺序反转)

问题:

难度:medium

说明:

给出一个字符串,去掉首位空格,然后把里面用空格隔开的每个单词位置都反转,然后翻转后的字符串单词之间,只隔着一个空格。

问题链接:https://leetcode.com/problems/reverse-words-in-a-string/

输入案例:

Example 1:
Input: "the sky is blue"
Output: "blue is sky the"

Example 2:
Input: "  hello world!  "
Output: "world! hello"
Explanation: Your reversed string should not contain leading or trailing spaces.

Example 3:
Input: "a good   example"
Output: "example good a"
Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string.

我的代码:

首先我注意到了,用 c 写算法的人需要用时间复杂度 O(1),这就意味着,用一个数组处理绝对可以(c语言的字符串就一数组)。然后就可以想象自己写了个 log(n) 的算法就可以了。

编译原理里面有介绍可以用:开始指针 + 向前指针,确定一个串,然后二分翻转就好。

代码思路是从:先全部逐个遍历 => 改为二分遍历 => 添加空格数量

class Solution {
    public String reverseWords(String s) {
        // 去空格
        s = s.trim();
        int space = 0;
        int len = s.length();
        char[] chs = s.toCharArray();
        // 反转整个数组
        divide(chs, 0, len, space);

        int begin = 0;
        boolean next = true;
        for(int forward = 0;forward < len;forward ++) {
            // 第一次遇到空格,就把词素反转
            if(chs[forward] == ' ') {
                if(next) {
                    divide(chs,begin,forward, space);
                    begin = forward + 1 - space;
                    next = false;
                } else space ++;
            } else {
                next = true;
            }
        }

        // 还有最后一个需要反转
        divide(chs, begin, len, space);

        return new String(chs, 0, len - space);
    }

    // 结合偏移量二分翻转词素
    // 切一半(二分)反转词素,然后如果空格超过一半,就只反转词素长度次数(
    public void divide(char[] chs, int begin, int end, int space) {
        int len = end + begin;
        int d = space > len >> 1 ? len - space : len >> 1;
        for(int i = begin;i < d;i ++) {
            char c = chs[i];
            chs[i] = chs[len - i - 1];
            chs[len - i - 1] = c;
        }
    }
}

如果没考虑空格的偏移量,就会差一点

 class Solution {
    public String reverseWords(String s) {
        s = s.trim();
        int len = s.length();
        char[] chs = s.toCharArray();
        divide(chs, 0, len);
        
        int end = 0;
        boolean next = true;
        int space = 0;
        for(int i = 0;i < len;i ++) {
            if(chs[i] == ' ') {
                if(next) {
                    divide(chs,end,i);
                    end = i + 1 - space;
                    next = false;
                } else space ++;
            } else {
                next = true;
            }
        }
        
        divide(chs, end, len);
        
        return new String(chs, 0, len - space);
    }
    
    // 少传入了空格偏移量
    public void divide(char[] chs, int begin, int end) {
        int len = end + begin;
        int d = len >> 1;
        for(int i = begin;i < d;i ++) {
            char c = chs[i];
            chs[i] = chs[len - i - 1];
            chs[len - i - 1] = c;
        }
    }
}

如果直接全部遍历,逐个翻转就更慢

class Solution {
    public String reverseWords(String s) {
        s = s.trim();
        int len = s.length() - 1;
        
        int begin = 0;
        boolean next = true;
        // 新建一个数组吃内存
        char[] newChs = new char[len + 1];
        int space = 1;
        // 全部都进行遍历
        for(int i = 0;i <= len;i ++) {

            // 遇到一次空格全部进行翻转
            if(s.charAt(i) == ' ') {
                if(next) {
                    for(int j = begin;j < i;j ++) {
                        newChs[len - i - begin + j + space] = s.charAt(j);
                    }
                    newChs[len - i + space - 1] = ' ';
                    begin = i + 1;
                    next = false;
                } else {
                    space ++;
                    begin ++;
                }
            } else next = true;
        }
        
        for(int j = begin;j <= len;j ++) {
            newChs[j - begin + space - 1] = s.charAt(j);
        }
        return new String(newChs, space - 1, len + 2 - space);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_28033719/article/details/107386312