【问题标题】:Using Recursion to Reverse a String使用递归反转字符串
【发布时间】:2017-07-20 02:34:25
【问题描述】:

我正在尝试使用递归逐字反转字符串。 (例如:“你好我的朋友”被反转为“朋友我的你好”)这是我试图为这个方法编写的代码。我尝试了多种类似的变体,但输出只是字符串的第一个或最后一个单词。我相信“损坏”的部分是第一个 if 语句,但我不太确定。

public static String reverse (String words) {
   Scanner sc = new Scanner(words);
   String backwards = "";

   if (sc.hasNext()) {
     String currentWord = sc.next();
     reverse(sc.nextLine());
     backwards = backwards + " " + currentWord;
   } //end if
   else {
     backwards = words;
   } //end else

   return backwards;
 }

我知道存在一些类似的问题,但他们的回答似乎无法帮助我理解我的错误。

谢谢!

【问题讨论】:

  • 您没有保存递归调用的结果。
  • 我去看看,谢谢! @JornVernee
  • 我对 StringBuilder 的工作不多,我会研究一下! @OusmaneDiaw
  • @Gabbie 如果你愿意,我可以为你提供 stringbuilder 的解决方案。
  • @OusmaneDiaw 当然!我会很感激的:)

标签: java string recursion reverse


【解决方案1】:

您可以使用String.split 的重载将words 拆分为第一个空格,而不是使用Scanner

public static String reverse(String words) {
    String[] wordArr = words.split(" ", 2); // split into a maximum of 2 Strings

    if (wordArr.length > 1) { // If there is more than 1 word
        // return the first word (wordArr[0]),
        // behind the reverse of the rest of the String (wordArr[1])
        return reverse(wordArr[1]) + " " + wordArr[0];
    }

    return wordArr[0]; // else, just return the one word
}

【讨论】:

  • 这解决了我的问题,简单明了,谢谢!! :)
【解决方案2】:

你不应该打电话给nextLine(),因为你的输入都在一行上。如果您从创建一个简单的辅助方法开始,您的逻辑会更加清晰,它应该采用words 的数组和一个位置;从那里你可以递归地构建你想要的输出,比如

private static String reverse(String[] words, int p) {
    if (p + 1 < words.length) {
        return reverse(words, p + 1) + " " + words[p];
    } else if (p < words.length) {
        return words[p];
    }
    return "";
}

那么你的public方法很容易实现,只需split在空白处输入原始输入并从0开始调用reverse(记住return的结果)。喜欢,

public static String reverse(String words) {
    return reverse(words.split("\\s+"), 0);
}

然后,我像这样测试它

public static void main(String[] args) {
    System.out.println(reverse("Hello my friend"));
}

哪些输出(根据要求)

friend my Hello

或者,你可以让那个助手拿你的Scanner代替像

private static String reverse(Scanner sc) {
    if (sc.hasNext()) {
        String currentWord = sc.next();
        if (sc.hasNext()) {
            return reverse(sc) + " " + currentWord;
        }
        return currentWord;
    }
    return "";
}

然后你的公共方法是

public static String reverse(String words) {
    return reverse(new Scanner(words));
}

【讨论】:

    【解决方案3】:

    你扔掉递归结果:

     reverse(sc.nextLine());
     backwards = backwards + " " + currentWord;
    

    改用这个:

     backwards = reverse(sc.nextLine());
     backwards = backwards + " " + currentWord;
    

    更好:

     backwards = reverse(sc.nextLine()) + " " + currentWord;
    

    【讨论】:

    • 我刚刚尝试了这个建议,我得到了 NoSuchElementException,知道为什么吗?
    • 如果您可以通过MCVE 发布问题,我会看看它。您当前的代码不足以执行到问题点。
    • 我想我明白了。您正在寻找下一行,而不是扫描当前行的其余部分。修复:正如其他人所建议的那样,完全转储扫描器并只处理字符串包。找到下一个空格,在该点分成两个子字符串,并在字符串的其余部分上递归。
    【解决方案4】:

    如 cmets 中所述,您可以使用 StringBuilder 代替 Scanner 类。

    此示例发送相同的单词,每次输入方法时将它们用空格分隔,然后发送要在下一次迭代中添加的单词的索引。

    例如:

    public class RecursiveReverse {
    
        static StringBuilder sb = new StringBuilder();
    
        public static void main(String[] args) {
            String stringToReverse = "Hello my friend!";
            System.out.println(reverse(stringToReverse, stringToReverse.split(" ").length - 1));
        }
    
        public static String reverse(String words, int i) {
            if (i >= 0) { //If the index of the words is greater or equals the first word
                sb.append(words.split(" ")[i]); //We split it and append it to our StringBuilder
                sb.append(" "); //We append a space
                reverse(words, --i); //We do this again
            }
            return sb.toString(); //When the above condition doesn't match we return the StringBuilder object as a String (which contains the words reversed)
        }
    }
    

    产生这个输出:

    friend! my Hello 
    

    更好的方法是传递一个字符串数组作为参数,这样你就只拆分一次字符串(当将单词作为数组发送给方法时)。

    public class RecursiveReverse {
    
        static StringBuilder sb = new StringBuilder();
    
        public static void main(String[] args) {
            String stringToReverse = "Hello my friend!";
            String words[] = stringToReverse.split(" ");
            System.out.println(reverse(words, words.length - 1));
        }
    
        public static String reverse(String words[], int i) {
            if (i >= 0) {
                sb.append(words[i]);
                sb.append(" ");
                reverse(words, --i);
            }
            return sb.toString();
        }
    }
    

    【讨论】:

      【解决方案5】:
      public static String reverseSentence(String sentence) {
      
          StringBuilder sb = new StringBuilder();
      
          int firstSpace = sentence.indexOf(' ');
          if (firstSpace == -1) {
              return sb.append(sentence.strip()).append(" ").toString();
          }
          String secondPart = sentence.substring(firstSpace + 1); 
          String firstPart = sentence.substring(0, firstSpace);//similar to merger sort 
          return sb.append(reverseSentence(secondPart)).append(reverseSentence(firstPart)).toString();
      }
      

      【讨论】:

        【解决方案6】:

        你必须使用递归吗?没有它你也可以做到。

        public static String reverse(String words) {
            String[] list = words.split(" ");
            Collections.reverse(list);
            String reversed = String.join(" ", list);
            return reversed;
        }
        

        【讨论】:

        • 感谢您的输入,但我必须使用递归 :)
        【解决方案7】:

        您必须在累加器中的调用之间保留提取的单词。这是一个例子。

        public static String reverse(String words, String acc){
            Scanner sc = new Scanner(words);
        
            if(!sc.hasNext()){
                return acc;
            }
        
            return reverse(sc.nextLine(), acc) + " " + sc.next();
        }
        

        你可以这样称呼它。

        reverse("Hello my friend", "");
        

        这不是世界上最有效的实现,但是是的......它必须有效!

        如果您想要更高效的,请使用StringBuilder 作为累加器。

        【讨论】:

          猜你喜欢
          • 2011-07-28
          • 2015-09-27
          • 2017-06-11
          • 1970-01-01
          • 1970-01-01
          • 2015-04-21
          • 2016-03-05
          相关资源
          最近更新 更多