Java: Find out if a number is prime recursively
我正在编写一个函数,如果数字是素数,则返回true,否则返回false
这是我当前的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public static boolean checkPrime(int n, int currDivisor){ if(n < 2){ return true; } if(currDivisor == (n/2)){ return true; } else if(n % currDivisor == 0 ){ return false; } else{ return checkPrime(n, currDivisor + 1); } } public static void main(String[] args){ System.out.println(checkPrime(23352, 2)); } |
它适用于许多测试用例,但" 1000000007"之类的数字会出现内存不足错误。 如何调整此代码以提高空间效率?
根本问题是递归不是正确的方法。原始性测试不是递归问题,对于大量存储,您将始终很快超过可用存储。我建议您在网络上进行有关"原始性测试"的研究。
关于确定问题是否递归的经验法则,我已经做了很久了,我不确定我能否表达出已经完全直观的内容,所以我会让别人去做。
但是,值得指出的是,某些数学上递归的问题具有计算解决方案,其迭代远比幼稚的递归好得多。素数(哈!)的例子是斐波那契数。对于较大的n,天真的递归解决方案会占用内存并执行冗余计算,而迭代解决方案在整个过程中都更快,更好。
我看到的第一个问题是您的程序是越野车。似乎认为0、1,&4是质数,而3不是。我看到的第二个问题是,它浪费了堆栈帧,在递归之前没有正确处理简单的情况。这是我对您的代码的重做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public static boolean checkPrime(int n) { return checkPrime1(n, 3); } public static boolean checkPrime1(int n, int currDivisor) { if (n < 2) { return false; } if (n % 2 == 0) { return (n == 2); } if (currDivisor * currDivisor > n) { return true; } if (n % currDivisor == 0) { return false; } return checkPrime1(n, currDivisor + 2); } |
至于处理:
1 |
您仍然会得到一个
您可以更改分配给Java堆栈的内存量-使用
如果将上面的三个
我并不是说这是递归的好问题,不是。但是,如果您要使用递归,请明智地使用它。不好的递归使递归变得不好名。递归的Fibonnaci算法效率不高(通常是双重递归),高效的(单一递归)算法也有。递归代码通常最适合递归数据。
某些语言(不是Java一致的语言)可以将上述代码作为尾部递归进行优化,并使其具有有效的迭代性能。