【问题标题】:Java Count the x's in a given string recusivelyJava递归计算给定字符串中的x
【发布时间】:2017-04-28 22:27:12
【问题描述】:

给定一个字符串,递归(无循环)计算字符串中小写“x”字符的数量。

countX("xxhixx") → 4

countX("xhixhix") → 3

countX("hi") → 0

我的尝试:

public int countX(String str) {
  int sum = 1;
  if(str.length()-1==0){
    return sum;
  }
  else{
    if(str.charAt(0)=='x'){
      return sum+countX(str.substring(1));

    }
    if(str.charAt(0)!='x'){
      return countX(str.substring(1));
    }
  }
}

我收到以下错误消息:This method must return a result of type int. 甚至不确定我的基本情况是否正确。有什么提示吗?

【问题讨论】:

  • 条件句之外没有回报。
  • 可以看出==!=是互斥的,但是编译器不能。使用else 而不是!=
  • @chrylis:严格来说,互斥性在这里并不重要。重要的是,这两个 if 用尽了所有可能性。它们可以重叠——因此不会相互排斥——并且仍然可以。相反,它们可能是相互排斥的,但无法涵盖所有​​可能性。
  • @NPE 确实如此。在这种情况下,它们当然可以,但编译器仍然看不到它。

标签: java string recursion


【解决方案1】:
public int countX(String str) {
  if (str.length() == 0) return 0;
  int sum = 0;
  if(str.charAt(0) == 'x') sum = sum + 1;
  return sum + countX(str.substring(1));
}

【讨论】:

  • 您不需要sum 变量。您可以将其替换为单行:return (str.charAt(0) == 'x' ? 1 : 0) + countX(str.substring(1));
【解决方案2】:

如何使用 fall through 而不是显式使用 if/else,这在某些情况下会混淆编译器

public static int countX(final String str) {
    //base case
    if(str.length() == 0) {
       return 0;
    }
    else if(str.length() == 1) {
        return str.charAt(0) == 'x' ? 1 : 0;
    }
    //recursive step
    return str.charAt(0) == 'x' ? 1 + countX(str.substring(1)) : countX(str.substring(1));
}

【讨论】:

  • 如果你将一个空字符串传递给这个版本,就会发生不好的事情,因为基本情况假定至少有一个字符。
  • 谢谢。很不错。但是如果我输入空字符串呢?如果这样做,我会得到一个索引越界异常。
【解决方案3】:

并非所有代码路径都有返回(从愚蠢的编译器的角度来看)。从一开始总和似乎也是错误的。考虑:

public int countX(String str) {
  if(str.length()==0){
    return 0;
  } else if(str.charAt(0)=='x'){
    return 1 + countX(str.substring(1));
  } else {
    assert str.charAt(0)!='x';
    return countX(str.substring(1));
  }
}

或者:

public int countX(String str) {
  if(str.length()==0){
    return 0;
  }
  if(str.charAt(0)=='x'){
    return 1 + countX(str.substring(1));
  }
  assert str.charAt(0)!='x';
  return countX(str.substring(1));
}

炸鱼的方法很多:

public int countX(String str) {
  return str.isEmpty() ? 0 : (
    (str.charAt(0)=='x' ? 1 : 0)
    + countX(str.substring(1))
  );
}

想要更简洁、可读性更差?

public int countX(String str) {
  return str.isEmpty()?0:countX(str.substring(1))+str.charAt(0)=='x'?1:0;
}

抱歉,我喜欢玩代码混淆玩具。

【讨论】:

  • 数字 1 和 2 不适用于所有情况。 3 号确实有效,但我从未听说过断言。 4 号吓到我了,所以我没有测试它。
  • 数字 1 和 2 检查字符串长度不正确,已修复。我试图迭代地从您的原始代码中删除它,然后显示其他选项。只是我输入的示例 - 你真的运行过这些吗?
  • 关于断言:作为程序员,我们知道某个条件在特定条件下应该在逻辑上为真。我们可以在某种程度上捕获这些知识,并在调试模式下通过assert 语句对其进行检查。 assert 之后的表达式必须计算为 true,并且只会在启用断言时运行(通常是调试/开发时间,而不是生产时间)。
【解决方案4】:

要求通过函数的每个代码路径都必须返回一个值,编译器对你有点过于迂腐了:

if(str.charAt(0)=='x'){
  return sum+countX(str.substring(1));
}
if(str.charAt(0)!='x'){
  return countX(str.substring(1));
}
// <--- there's no return value here

可以说,编译器可以找出这两个 if 语句耗尽了所有可能性,但事实并非如此。

帮助编译器的一种方法是将两个 if 重新表述为一个 if-else:

if(str.charAt(0)=='x') {
  return sum+countX(str.substring(1));
} else {
  return countX(str.substring(1));
}

【讨论】:

  • 任何想法如何摆脱这个'int sum'?因为代码只有在我输入的字符串中有任何 x 时才有效。
  • @DerDieDasEhochWas:仔细考虑你的基本情况。您当前的代码永远不会返回零。此外,它不能正确处理长度为 1 的字符串。我认为通过这些提示您可以解决它。 :-)
  • 我明白了。非常感谢。 :)
  • @DerDieDasEhochWas:我很高兴。 :)
【解决方案5】:

应该这样做。

public int countX(String str) {
  int sum = 0;
  if(str.length()-1!=0){
    sum = countX(str.substring(1));
    if(str.charAt(0)=='x'){
      sum += 1;
    }
  }
  return sum;
}

您的问题是,在某些情况下,没有回报。 避免这种情况的一种方法是在方法末尾使用单个返回指令,或者您可以像这样在代码中简单地添加一些其他情况:

  [...]
  else{
    if(str.charAt(0)=='x'){
      return sum+countX(str.substring(1));
    }else{
      return countX(str.substring(1));
    }
  }
  [...]

【讨论】:

    猜你喜欢
    • 2020-03-15
    • 2017-10-18
    • 2013-07-21
    • 2014-03-31
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    相关资源
    最近更新 更多