您如何编写非递归算法来计算n!
?
答案 0 :(得分:27)
因为Int32会在大于12的任何东西上溢出!无论如何,只是做:
public int factorial(int n) {
int[] fact = {1, 1, 2, 6, 24, 120, 720, 5040, 40320,
362880, 3628800, 39916800, 479001600};
return fact[n];
}
答案 1 :(得分:18)
在伪代码中
ans = 1
for i = n down to 2
ans = ans * i
next
答案 2 :(得分:6)
为了科学的利益,我对各种算法实现进行了一些分析,以计算因子。我创建了迭代,查找表,以及C#和C ++中每个的递归实现。我将最大输入值限制在12或更低,因为13!大于2 ^ 32(最大值能够保存在32位int中)。然后,我运行每个函数1000万次,循环通过可能的输入值(即使用i modulo 13作为输入参数将i从0增加到1000万)。
以下是规范化为迭代C ++数字的不同实现的相对运行时间:
C++ C#
---------------------
Iterative 1.0 1.6
Lookup .28 1.1
Recursive 2.4 2.6
并且,为了完整性,以下是使用64位整数并允许输入值最多为20的实现的相对运行时间:
C++ C#
---------------------
Iterative 1.0 2.9
Lookup .16 .53
Recursive 1.9 3.9
答案 3 :(得分:5)
public double factorial(int n) {
double result = 1;
for(double i = 2; i<=n; ++i) {
result *= i;
}
return result;
}
答案 4 :(得分:5)
除非像Python中那样有任意长度的整数,否则我会将factorial()的预先计算值存储在大约20个long的数组中,并使用参数n作为索引。 n的增长率!相当高,计算20!或21!无论如何,即使在64位计算机上也会出现溢出。
答案 5 :(得分:4)
将循环解决方案重写为循环。
答案 6 :(得分:3)
这是预先计算的功能,但实际上是正确的。如前所述,13!溢出,所以计算如此小范围的值是没有意义的。 64位更大,但我希望范围仍然相当合理。
int factorial(int i) {
static int factorials[] = {1, 1, 2, 6, 24, 120, 720,
5040, 40320, 362880, 3628800, 39916800, 479001600};
if (i<0 || i>12) {
fprintf(stderr, "Factorial input out of range\n");
exit(EXIT_FAILURE); // You could also return an error code here
}
return factorials[i];
}
答案 7 :(得分:2)
long fact(int n) {
long x = 1;
for(int i = 1; i <= n; i++) {
x *= i;
}
return x;
}
答案 8 :(得分:2)
int total = 1
loop while n > 1
total = total * n
n--
end while
答案 9 :(得分:2)
我喜欢这种pythonic解决方案:
def fact(n): return (reduce(lambda x, y: x * y, xrange(1, n+1)))
答案 10 :(得分:1)
public int factorialNonRecurse(int n) {
int product = 1;
for (int i = 2; i <= n; i++) {
product *= i;
}
return product;
}
答案 11 :(得分:1)
在运行时,这是非递归的。在编译时它是递归的。运行时性能应为O(1)。
//Note: many compilers have an upper limit on the number of recursive templates allowed.
template <int N>
struct Factorial
{
enum { value = N * Factorial<N - 1>::value };
};
template <>
struct Factorial<0>
{
enum { value = 1 };
};
// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
int x = Factorial<4>::value; // == 24
int y = Factorial<0>::value; // == 1
}
答案 12 :(得分:0)
对于非递归方法,没有比这更简单的
int fac(int num) {
int f = 1;
for (int i = num; i > 0; i--)
f *= i;
return f;
}
答案 13 :(得分:0)
Java中的非递归阶乘。这个解决方案是使用自定义迭代器(以演示迭代器使用:))。
/**
* Non recursive factorial. Iterator version,
*/
package factiterator;
import java.math.BigInteger;
import java.util.Iterator;
public class FactIterator
{
public static void main(String[] args)
{
Iterable<BigInteger> fact = new Iterable<BigInteger>()
{
@Override
public Iterator<BigInteger> iterator()
{
return new Iterator<BigInteger>()
{
BigInteger i = BigInteger.ONE;
BigInteger total = BigInteger.ONE;
@Override
public boolean hasNext()
{
return true;
}
@Override
public BigInteger next()
{
total = total.multiply(i);
i = i.add(BigInteger.ONE);
return total;
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
};
}
};
int i = 1;
for (BigInteger f : fact)
{
System.out.format("%d! is %s%n", i++, f);
}
}
}
答案 14 :(得分:0)
迭代:
int answer = 1;
for (int i = 1; i <= n; i++){
answer *= i;
}
或者......在Haskell中使用尾递归:
factorial x =
tailFact x 1
where tailFact 0 a = a
tailFact n a = tailFact (n - 1) (n * a)
在这种情况下,尾递归的作用是使用累加器来避免堆栈调用堆积。
答案 15 :(得分:0)
long fact(int n)
{
long fact=1;
while(n>1)
fact*=n--;
return fact;
}
long fact(int n)
{
for(long fact=1;n>1;n--)
fact*=n;
return fact;
}
答案 16 :(得分:0)
我会使用memoization。这样您就可以将该方法编写为递归调用,并且仍然可以获得线性实现的大部分好处。
答案 17 :(得分:0)
假设您希望能够处理一些非常庞大的数字,我会按如下方式编写代码。这种实现方式适用于普通情况(低数字)需要相当大的速度,但希望能够处理一些超级大量的计算。我认为这是理论上最完整的答案。在实践中,我怀疑你需要为家庭作业问题以外的任何事情计算这么大的因子
#define int MAX_PRECALCFACTORIAL = 13;
public double factorial(int n) {
ASSERT(n>0);
int[MAX_PRECALCFACTORIAL] fact = {1, 1, 2, 6, 24, 120, 720, 5040, 40320,
362880, 3628800, 39916800, 479001600};
if(n < MAX_PRECALCFACTORIAL)
return (double)fact[n];
//else we are at least n big
double total = (float)fact[MAX_PRECALCFACTORIAL-1]
for(int i = MAX_PRECALCFACTORIAL; i <= n; i++)
{
total *= (double)i; //cost of incrimenting a double often equal or more than casting
}
return total;
}
答案 18 :(得分:0)
fac = 1 ;
for( i = 1 ; i <= n ; i++){
fac = fac * i ;
}
答案 19 :(得分:0)
伪代码
total = 1
For i = 1 To n
total *= i
Next
答案 20 :(得分:-1)
int fact(int n){
int r = 1;
for(int i = 1; i <= n; i++) r *= i;
return r;
}
答案 21 :(得分:-2)
递归地使用JavaScript进行缓存。
var fc = []
function factorial( n ) {
return fc[ n ] || ( ( n - 1 && n != 0 ) &&
( fc[ n ] = n * factorial( n - 1 ) ) ) || 1;
}