Java 使用递归查找字符串中的字符

Java 使用递归查找字符串中的字符,java,string,recursion,Java,String,Recursion,我正在尝试查找字符串中字母的第一个匹配项。例如,苹果中的p应该返回1。以下是我所拥有的: // Returns the index of the of the character ch public static int indexOf(char ch, String str) { if (str == null || str.equals("")) { return -1; } else if(ch == str.charAt(0)) { re

我正在尝试查找字符串中字母的第一个匹配项。例如,苹果中的p应该返回1。以下是我所拥有的:

// Returns the index of the of the character ch
public static int indexOf(char ch, String str) {

    if (str == null || str.equals("")) {
        return -1;
    } else if(ch == str.charAt(0)) {
        return 1+ indexOf(ch, str.substring(1));
    }

    return indexOf(ch, str.substring(1));
}

它似乎没有返回正确的值。

我将给您一些提示:

  • 找到该字母后,无需再重复。此外,考虑在这种情况下您应该返回什么
  • 当您递归时,还要考虑函数应该返回什么
  • 如果递归调用返回
    -1
    ,您需要执行什么特殊操作吗

  • 为什么不直接做呢

    public static void main(String[] args) {
        String str = "abcdef";
        for (int idx = 0; idx < str.length(); idx++) {
            System.out.printf("Expected %d, found %d\n", idx, indexOf(str.charAt(idx), str, 0));
        }
        System.out.printf("Expected -1, found %d\n", indexOf(str.charAt(0), null, 0));
    }
    
    public static int indexOf(char ch, String str, int index) {
        if (str == null || index >= str.length()) return -1;
        return str.charAt(index) == ch ? index : indexOf(ch, str, ++index);
    }
    

    如果我们必须使用递归,那么请尝试以下方法:

    class RecursiveFirstIndexOf {
    
    public static void main(String[] args) {
        System.out.println(indexOf('p', "apple", 0));
    }
    
    static int indexOf(char c, String str, int currentIdx) {
    
        if (str == null || str.trim().isEmpty()) {
            return -1;
        }
    
        return str.charAt(0) == c ? currentIdx : indexOf(c, str.substring(1), ++currentIdx);
    
    }}
    
    首先:递归有两个支柱,基本情况和一般情况

    基本情况(终止点)是递归终止的情况,顾名思义,一般情况是程序在找到基本情况之前一直执行的情况

    您可以尝试此示例,其中
    count
    是一个全局
    static
    变量

    public static int indexOf(char ch, String str)
    {
      // Returns the index of the of the character ch
      if (str == null || str.Equals(""))     //Base Case
      {
         if (count != 0)
         {
            if(str.Length == 0)
               return -1;  
            return count;
         }
         else
            return -1;          
      }
      else if (ch == str.CharAt(0))          //Base Case  
         return 1 + count; 
      count++;
      return indexOf(ch, str.Substring(1));  //General Case
    }
    

    这是另一个变体。您可以稍微修改函数以传递下一个要检查的索引,而不是调用子字符串。请注意,递归是使用索引0启动的。(实际上,您可以从任何索引开始。如果找不到该字母,还会进行一些错误检查。在apple中查找x将返回-1。)

    输出:

    Index: 4 Index: -1 Index: 8 Index: -1 索引:4 索引:-1 索引:8 索引:-1
    你的尝试很好,但不完全成功。以下是基于您的正确实现:

    public static int indexOf(char ch, String str) {
        // Returns the index of the of the character ch
    
        if (str == null || str.equals("")) {
            // base case: no more string to search; return -1
            return -1;
        } else if (ch == str.charAt(0)) {
            // base case: ch is at the beginning of str; return 0
            return 0; 
        }
    
        // recursive step
        int subIndex = indexOf(ch, str.substring(1));
    
        return subIndex == -1 ? -1 : 1 + subIndex;
    }
    
    您的尝试有两个问题:

    else if
    部分中,您已经找到了字符,因此正确的做法是停止递归,但您正在继续它


    在上一个return语句中,需要向递归调用中添加1(如果最终找到该字符),作为累计总索引数的方法。

    有什么原因不使用?@LutzHorn作业-愿意下注吗?:)这是一个问题,不是一个答案我的意思是indexOf已经由Java提供了,那么为什么不使用它而不是编写方法来做同样的事情呢?我知道,但问题是:“使用递归”,而不是任何内置方法。无论如何,这不是一个问题。在字符串中递归查找字母索引的唯一原因是练习递归。这就是关键词:练习。OP可能只是学习Java,这是家庭作业、实验室作业或类似的学术问题。使用静态变量来实现这一点不是一个好主意。这也有一个off by one错误,如果字符串不包含请求的字符,则会产生完全错误的结果。@JLRishe根据您的说明,我已经修复了“字符不存在的情况”,并且我使用了static,因为我不想更改用户函数的原型(即使用额外参数),无论如何,谢谢你的评论。
    idx=indexOf(ch,str,++idx)这让我畏缩。为什么不
    返回indexOf(ch,str,idx+1)
    ?@JLRishe:我刚刚发布了一篇关于你评论落地时畏缩的编辑文章。:-)确实是这样我仍然认为
    idx+1
    在这里更好。没有理由增加
    idx
    变量。@JLRishe:+1很好。idx+1更具可读性和直观性,尤其是对于新手而言。不知道我为什么做前缀的事。我想是因为大脑上的循环。我本来打算投票,但注意到你的逻辑至少有一个缺陷。如果你尝试一个不在字符串中的字母,你只会得到最后一个字母的索引。@PaulSasik看起来像是你和我同时注意到的。现在应该修好了。酷+1和其他一些words@JLRishe+1表示递归步骤。我想说,真的很聪明。在递归步骤中,我做的是“返回1 +索引(S.SUBR(1,S.LangthHe)),c),除了Paul Sasik指出的情况之外,在C++中工作得很好。我永远不会理解为什么人们在使用代码< >变量+1 字符太多时使用<代码> +变量> /代码>。 Index: 4 Index: -1 Index: 8 Index: -1
    public static int indexOf(char ch, String str) {
        // Returns the index of the of the character ch
    
        if (str == null || str.equals("")) {
            // base case: no more string to search; return -1
            return -1;
        } else if (ch == str.charAt(0)) {
            // base case: ch is at the beginning of str; return 0
            return 0; 
        }
    
        // recursive step
        int subIndex = indexOf(ch, str.substring(1));
    
        return subIndex == -1 ? -1 : 1 + subIndex;
    }