【算法】翻转单词顺序

50 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

题目

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。 "  hello world!  " ->"world! hello";"a good   example" -> "example good a"

解题思路

根据题意可知以下几点:

  1. 字符串需要倒装输出。
  2. 句子倒装但单词非倒装输出。
  3. 单词和单词之间空格只保留一个。

双指针解法

又使用到双指针解法,定义两个下标值来指定当前在字符串上移动位置。

  1. 双指针起始位置都在尾部。
  2. 首先移动left指针,先排除掉空格直到非空格为止。
  3. 然后移动left指针直到遇到空格为止。
  4. 使用substring截取到单词字段,然后将right指针指向left位置。
  5. 继续移动left指针重复上述操作,一直循环直到left指针指向0下标为止。
    public String reverseWords(String s) {
        // 双指针
        int left = s.length() - 1; 
        int right = left; // 起始位置都在尾部
        StringBuilder stringBuilder = new StringBuilder();
        while(left > 0 && s.charAt(left) == ' ') left --;
        right = left;
        while(left >= 0){
            while(left >= 0 && s.charAt(left) != ' ') left --; // 直到为空格
            stringBuilder.append(s.substring(left + 1,right + 1)).append(" ");//截取单词
            while(left >= 0 && s.charAt(left) == ' ') left --; // 去空格
            right = left;
        }
        if(stringBuilder.length() > 0)
         stringBuilder.deleteCharAt(stringBuilder.length()-1); // 去掉多余的空格
        return stringBuilder.toString();
    }

巧用语法解法

巧解法使用到String类方法以及List类方法。

  1. 先用trim去掉首尾多余空格。
  2. 正则手段分割出每个单词组装成List。
  3. 列表集合reverse倒序重新排序。
  4. join方法重新为每个单词间加空格。

熟悉API采用巧解能够快速得到解题思路,主要对于语言够了解就能实现。

    public String reverseWords(String s) {
        // 除去开头和末尾的空白字符
        s = s.trim();
        // 正则匹配连续的空白字符作为分隔符分割
        List<String> words = Arrays.asList(s.split("\s+"));
        Collections.reverse(words);
        return String.join(" ", wordList);
    }

分割倒序解法

分割倒序法综合了上述两种解法,字符串分割加上倒序并运用API方法。

  1. 先用trim去掉首尾多余空格并分割字符串得到每块单词。
  2. 倒序遍历每个单词块字符重新拼接字符串。
  3. 最后通过trim去掉尾部多余空格。
    public String reverseWords(String s) {
        String[] strs = s.trim().split(" "); // 删除首尾空格,分割字符串
        StringBuilder res = new StringBuilder();
        for(int i = strs.length - 1; i >= 0; i--) { // 倒序遍历单词列表
            if(strs[i].equals("")) continue; // 遇到空单词则跳过
            res.append(strs[i] + " "); // 将单词拼接至 StringBuilder
        }
        return res.toString().trim(); // 转化为字符串,删除尾部空格,并返回
    }

参考