【问题标题】:Reverse the words in a sentence but not punctuation using recursion使用递归反转句子中的单词而不是标点符号
【发布时间】:2021-07-27 05:47:02
【问题描述】:

如何使用递归来反转句子中的单词,而不是标点符号。据说该句子使用标点符号:,.?!

输入:“杰克,回家吧!”

输出:“回家,杰克来了!”

现在我以某种方式设法正确完成了任务,但没有使用递归。 我应该如何将这项工作转换为使用递归来解决问题?

方法如下:

public static StringBuilder reverseSentenceWithPunctuation(String sentence, int i) {
        String[] parts = sentence.split(" ");
        StringBuilder newSentence = new StringBuilder();
        Map<Integer, Character> punctuationMap = new HashMap<>();

        for (int j = 0; j < parts.length; j++) {
            if (parts[j].endsWith(",") || parts[j].endsWith(".") || parts[j].endsWith("!") || parts[j].endsWith("?")) {
                char lastSymbol = parts[j].charAt(parts[j].length()-1);
                punctuationMap.put(j, lastSymbol);
                String changedWord = parts[j].replace(String.valueOf(lastSymbol), "");
                parts[j] = changedWord;
            }
        }

        for (int j = parts.length-1; j >= 0; j--) {
            newSentence.append(parts[j]);
            if (punctuationMap.containsKey(i)) {
                newSentence.append(punctuationMap.get(i));
                newSentence.append(" ");
            } else
                newSentence.append(" ");
            i++;
        }
        return newSentence;
    }

提前致谢!

【问题讨论】:

  • idk 为什么你应该这样做,但你几乎可以在递归中转换一个 for 循环,创建一个带有“你需要的参数 + 索引”的函数(从循环的起始值开始,在您的情况下 0 和 parts.length-1) 然后将类似 if(condition of the loop) return; 的内容作为第一行然后放入循环体,然后在底部调用函数本身,并根据您的第三条指令增加或减少索引 for循环

标签: java string recursion reverse


【解决方案1】:

我认为这不是递归函数的好案例,主要是因为您需要 2 个循环。此外,一般来说,迭代算法在性能方面更好,并且不会引发 stackoverflow 异常。

所以我认为使用递归函数的主要原因是可读性和易用性,老实说,在这种情况下,我认为它不值得。

无论如何,这是我将您的代码转换为递归函数的尝试。如前所述,由于有 2 个循环,我使用了 2 个函数。我确信有一种方法可以通过一个函数来实现这一点,该函数首先加载标点符号映射,然后组成最终的字符串,但老实说这会很丑。

import java.util.*;
import java.util.stream.*;

public class HelloWorld{

    static Character[] punctuationCharacters = {',','.','!'};

    public static void main(String []args){
        System.out.println(reverseSentenceWithPunctuation("Jack, come home!"));
    }
     
    private static String reverseSentenceWithPunctuation(String sentence) {
        
        String[] parts = sentence.split(" ");

        return generate(0, parts, extractPunctuationMap(0, parts));
    }
     
    private static Map<Integer, Character> extractPunctuationMap(int index, String[] parts){
        Map<Integer, Character> map = new HashMap<>();
        if (index >= parts.length) {
            return map;
        }
        char lastSymbol = parts[index].charAt(parts[index].length() - 1);
        if (Arrays.stream(punctuationCharacters).anyMatch(character -> character == lastSymbol)) {
            parts[index] = parts[index].substring(0, parts[index].length() - 1);
            map = Stream.of(new Object[][] { 
             { index,  lastSymbol}
            }).collect(Collectors.toMap(data -> (Integer) data[0], data -> (Character) data[1]));
        }
        map.putAll(extractPunctuationMap(index + 1, parts));
        return map;
    }
    
    private static String generate(int index, String[] parts, Map<Integer, Character> punctuationMap) {
        
        if (index >= parts.length) {
            return "";
        }
        String part = index == 0? " " + parts[index] : parts[index];
        if (punctuationMap.containsKey(parts.length -1 - index)) {
            part += punctuationMap.get(parts.length -1 - index);
        }
        return generate(index + 1, parts, punctuationMap) + part;
        
    }
}

【讨论】:

    【解决方案2】:

    在伪代码中可能是这样的:

    1. 取整句

    (一)。得到第一个单词

    (b)。得到最后一句话

    (如果第一个词或最后一个词后有标点符号,请留在那里)

    1. swap(a, b) 并返回句子的剩余中间部分
    2. 重复(1)和(2)直到只有两个或一个单词
    3. 返回剩下的最后两个(交换的)单词(如果是一个单词,就返回那个)

    【讨论】:

      【解决方案3】:

      要使用递归实现此任务,应准备一个匹配第一个和最后一个单词的模式,后跟一些分隔符:

      word1 del1 word2 del2 .... wordLast delLast
      

      在匹配输入的情况下,结果计算如下:

      wordLast del1 REVERT(middle_part) + word1 delLast
      

      示例实现可能如下(单词被认为包含英文字母和撇号'为缩写):

      static Pattern SENTENCE = Pattern.compile("^([A-Za-z']+)([^A-Za-z]+)?(.*)([^'A-Za-z]+)([A-Za-z']+)([^'A-Za-z]+)?$");
      
      public static String revertSentence(String sentence) {
          
          Matcher m = SENTENCE.matcher(sentence);
          if (m.matches()) {
              return m.group(5) + (m.group(2) == null ? "" : m.group(2)) 
                  + revertSentence(m.group(3) + m.group(4)) // middle part
                  + m.group(1) + (m.group(6) == null ? "" : m.group(6));
          }
          return sentence;
      }
      

      测试:

      System.out.println(revertSentence("Jack, come home!"));
      System.out.println(revertSentence("Jack, come home please!!"));
      System.out.println(revertSentence("Jane cried: Will you come home Jack, please, don't go!"));
      

      输出:

      home, come Jack!
      please, home come Jack!!
      go don't: please Jack home come you, Will, cried Jane!
      

      【讨论】:

      • 感谢您的帮助!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-03
      • 2020-02-13
      • 1970-01-01
      相关资源
      最近更新 更多