【问题标题】:Recursive method for prime numbers in JAVAJAVA中素数的递归方法
【发布时间】:2016-03-10 20:38:29
【问题描述】:

首先我知道这是一个简单的问题,我是初学者,所以请多多包涵。 我在 Java 中的这个练习中遇到了问题,我正在练习一个测试,这个真的搞砸了我的自信心。 所以无论如何问题看起来像这样

 // Returns true if (and only if) n is a prime number;  n > 1 is assumed.
private static boolean isPrime(long n) {
    return isPrime(n, 2);
    // See the method isPrime below.
}

// Helper method for isPrime ...
private static boolean isPrime(long n, long m) {
    return (m * n > (m /* TODO: modify expression if necessary */))
            || (n % m == (0 /* TODO: modify expression if necessary */)
                && isPrime((m /* TODO: modify expression if necessary */), n + 1));
}

因此,您应该将这些表达式填充到 TODO 所在的括号内。 我的问题是我无法追踪它的作用。

isPrime((.....),n+1); 

如果有人能就如何开始解决这个问题提供一些建议,我将不胜感激。

【问题讨论】:

  • 只有能被 1 和自身整除的数才是素数。对此的补充说明是,如果它可以被任何其他素数整除(即模数返回 0),则它不是素数。应该有助于思考问题。
  • 是的,我明白,问题是如果数字是素数并且 n%m == 0 的条件仅对非素数为真,则该方法应该返回 true。因此,如果 n 是一个将是 false 的素数,并且 false && true 仍然是 false ..
  • isPrime((m /* TODO: modify expression if necessary */), n + 1)) 正在检查除数 m 的素数,而不是 n。如果m 不是质数,则n 不是质数。
  • 如果我们以n=7为例,当方法第一次调用自身时,m参数是8?
  • 我明白你在说什么,但我不完全确定答案是什么,因为这是一种奇怪的递归方式。通常你会使用isPrime(n, m+1) 进行递归,但你的问题会转置mn

标签: java recursion boolean


【解决方案1】:

此问题不适用于递归解决方案。或者至少不是一个高效递归解决方案。

素数的定义是,如果 N 不能被除自身或 1 以外的任何正整数整除,则 N 为素数。使用递归处理该问题的正常方法是定义递归“is_divisible”函数:

# for integers m >= 1
is_prime(m):
    return is_divisible(m, 1)

is_divisible(m, n):
    if n >= m: return true
    if n == 1: return is_divisible(m, n + 1)
    if m % n == 0: return false  // HERE
    return is_divisible(m, n + 1)

OR(更高效的 3 参数版本)

# for all integers m
is_prime(m):
    if m == 1: return false
    if m >= 2: return is_divisible(m, sqrt(m), 2)
    error "m is not a positive integer"

is_divisible(m, max, n) :
    if n >= max: return true
    if m % n == 0: return false  // HERE
    return is_divisible(m, max, n + 1)

(在文献中,他们经常将is_divisible之类的函数称为“辅助”函数。这是函数式编程中的常用工具。)

如果您尝试“优化”它以仅考虑 HERE 处的素数,您最终会遇到双重递归......和指数复杂性。


这在 Java 中都是非常“不自然”的,而且效率极低(即使与使用循环1 的天真素数测试相比),因为 Java 不做递归的尾调用优化.事实上,对于足够大的N,你会得到一个StackOverflowError


1 - 一种更好但仍然简单的方法是 Erathones 筛法。有比这更好的素数测试,尽管它们相当复杂,并且在某些情况下是概率性的。

【讨论】:

  • 我们可以只用两个参数吗?只需使用 m/2 而不是 max ? is_divisible(m, n) :- if n >= m/2: return true if n == 1: return is_divisible(m, n + 1) if m % n == 0 : return false // HERE return is_divisible(m, n + 1) - 像这样?
  • 对于 3 参数版本,您应该使用 sqrt(m) 作为“最大值”。同样的优化适用于朴素循环和 Sieve 算法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-16
  • 2014-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多