作为编程分配的一部分,我需要编写一个递归函数来确定数组中的最大整数。引用确切的任务:
编写递归函数,找到给定列表中的最大数字 整数。
我提出了两个解决方案,第一个解决方案是两个递归调用:
int largest(int arr[], int length){
if(length == 0)
return 0;
else if(arr[length - 1] > largest(arr,length -1))
return arr[length];
else return largest(arr,length -1);
}
第二个只使用一个,但它使用静态变量n
:
int largest(int arr[], int length){
static int n = -1;
if(length == 0)
return n;
else if (arr[length - 1] > n)
n = arr[length - 1];
return largest(arr, length - 1);
}
我想知道是否会将作弊用于此类任务的静态变量。无论哪种方式,哪一种被认为是更好的形式?是否存在一种顶生于两者的递归方法?
答案 0 :(得分:8)
我不会说以这种方式使用import lxml
变量是作弊的 - 我会说这是不正确的。 : - )
想象一下,您在许多不同的阵列上多次调用此函数。引入静态变量后,static
的值永远不会在调用之间重置,因此最终可能会返回错误的值。一般来说,设置这样的编码风格通常很差,因为它很容易得到错误的答案。此外,如果您的数组仅包含负值,则可以返回-1作为答案,即使-1实际上更大而不是数组中的所有内容。
我认为第二个版本比第一个版本有一个很好的优势 - 它更快,更快,因为它只进行一次递归调用而不是两次。考虑使用第一个版本,但更新它以便缓存递归调用返回的值,这样就不会进行两次调用。这将以指数方式加速代码;初始版本需要时间Θ(2 n ),而更新版本需要时间Θ(n)。
答案 1 :(得分:5)
没有任何作弊使用静态内部函数,递归或其他方式。
为什么这样做有很多充分的理由,但在你的情况下,我怀疑你提出了一个错误的解决方案 - 因为largest
只会在程序运行的一生中工作一次它
考虑以下(伪)代码;
main() {
largest([ 9, 8, 7]) // would return 9 -- OK
largest([ 1, 2, 3]) // would return 9 ?? bad
}
原因是你的largest
无法区分这两个电话,但如果这就是你想要的,那就没关系。
修改强> 在回答你的评论时,像这样的东西会比你的初始代码有更好的大写符号;
int largest(int arr[], int length){
int split, lower,upper;
switch (length) {
case 1: return arr[0];
case 2: if (arr[1]>arr[0]) return arr[1]; else return arr[0];
default:
if (len <= 0) throw error;
split = length/2;
lower = largest(arr,split);
upper = largest(arr+split,length-split);
if (lower > upper) return lower; else return upper;
}
}
或者,明显的解决方案是;
int largest(int arr[], int length){
if (length <= 0) thor error;
int max = arr[0];
for (int i=1; i<length; i++)
if (arr[i] > max) max = arr[i];
return max;
}
根本没有递归
答案 2 :(得分:3)
它实际上是一个糟糕的设计,因为在第二次执行该函数时不会返回正确的结果。
如果错误的话,我认为你不需要辩论它是否在作弊。
第一个版本也不正确,因为您返回的是arr[length]
而不是arr[length-1]
。您可以消除第二次递归调用。您可以做什么而不是使用相同的参数调用相同的函数(没有副作用)两次?
答案 3 :(得分:1)
除了前三个答案中的优点之外,你应该练习更多基于递归的思维。 (1)处理琐碎的案件。 (2)对于一个非平凡的案例,减少任务并重复(较小的)剩余问题。
我建议你的正确基础案例是一个项目的列表:返回该项目。空列表没有最大元素。
对于递归情况,检查第一个元素与列表其余部分的最大值;返回更大。在近代码形式中,这看起来如下所示。它只进行一次递归调用,并且只有一个显式局部变量 - 这就是作为递归结果的别名。
int largest(int arr[], int length){
if(length == 1)
// if only one element, return it
return arr[0];
else n = largest(arr,length-1))
// return the larger of the first element or the remaining largest.
return arr[length-1] > n ? arr[length-1] : n
}
答案 4 :(得分:1)
是否存在一个超过两者的递归方法?
使用/**
* Draws a route on a map.
*/
public class MapRouteDrawer {
private static final SplineInterpolator splineInterpolator = new SplineInterpolator();
/**
* Draws the route to the screen, does nothing if null.
*/
public static void drawRoute(final Graphics2D graphics, final RouteDescription routeDescription, final MapPanel view, final MapData mapData, final String movementLeftForCurrentUnits) {
if (routeDescription == null) {
return;
}
final Route route = routeDescription.getRoute();
if (route == null) {
return;
}
final Point[] points = getRoutePoints(routeDescription, mapData);
final int xOffset = view.getXOffset();
final int yOffset = view.getYOffset();
final int jointsize = 10;
final int numTerritories = route.getAllTerritories().size();
//set thickness and color of the future drawings
graphics.setStroke(new BasicStroke(3.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
graphics.setPaint(Color.red);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if(Arrays.asList(points).contains(null)){//If the Array is null at some point
return;
}
if(numTerritories <= 1 || points.length <= 2){
drawLineWithTranslate(graphics, new Line2D.Float(routeDescription.getStart(), routeDescription.getEnd()), xOffset, yOffset);
graphics.fillOval((routeDescription.getEnd().x - xOffset) - jointsize / 2, (routeDescription.getEnd().y - yOffset) - jointsize / 2, jointsize, jointsize);
}
else{
drawCurvedPath(graphics, points, view);
}
}
}
private static double[] getIndex(Point[] points) {
final double[] index = new double[points.length];
for(int i = 0; i < points.length; i++){
index[i] = i;
}
return index;
}
private static void drawLineWithTranslate(Graphics2D graphics, Line2D line2D, double translateX, double translateY) {
final Line2D line = (Line2D) line2D;
final Point2D point1 = new Point2D.Double(line.getP1().getX() - translateX, line.getP1().getY() - translateY);
final Point2D point2 = new Point2D.Double(line.getP2().getX() - translateX, line.getP2().getY() - translateY);
graphics.draw(new Line2D.Double(point1, point2));
}
private static Point[] getRoutePoints(RouteDescription routeDescription, MapData mapData){
final List<Territory> territories = routeDescription.getRoute().getAllTerritories();
final int numTerritories = territories.size();
final Point[] points = new Point[numTerritories];
for (int i = 0; i < numTerritories; i++) {
points[i] = mapData.getCenter(territories.get(i));
}
if (routeDescription.getStart() != null) {
points[0] = routeDescription.getStart();
}
if (routeDescription.getEnd() != null && numTerritories > 1) {
points[numTerritories - 1] = new Point(routeDescription.getEnd());
}
return points;
}
private static double[] pointsXToDoubleArray(Point[] points){
double[] result = new double[points.length];
for(int i = 0; i < points.length; i++){
result[i] = points[i].getX();
}
return result;
}
private static double[] pointsYToDoubleArray(Point[] points){
double[] result = new double[points.length];
for(int i = 0; i < points.length; i++){
result[i] = points[i].getY();
}
return result;
}
private static double[] getCoords(PolynomialSplineFunction curve, float stepSize){
final double[] coords = new double[(int) (curve.getN() / stepSize)];
for(int i = 0; i < curve.getN() / stepSize; i++){
coords[i] = curve.value(i * stepSize);
}
return coords;
}
private static void drawCurvedPath(Graphics2D graphics, Point[] points, MapPanel view){
final double[] index = getIndex(points);
final float stepSize = 0.01f;//TODO calculating a step size that makes sense
final PolynomialSplineFunction xcurve = splineInterpolator.interpolate(index, pointsXToDoubleArray(points));
final PolynomialSplineFunction ycurve = splineInterpolator.interpolate(index, pointsYToDoubleArray(points));
final double[] xcoords = getCoords(xcurve, stepSize);
final double[] ycoords = getCoords(ycurve, stepSize);
for(int i = 1; i < xcoords.length; i++){
//TODO maybe a line is not the best way to draw this...
drawLineWithTranslate(graphics, new Line2D.Double(xcoords[i-1], ycoords[i-1], xcoords[i], ycoords[i]), view.getXOffset(), view.getYOffset());
}
}
}
元素导致递归深度N
与N
一样
为避免这种情况,请确保每次递归的长度减半
最大递归深度为return largest(arr,length -1);
O(log2(N))
一个偷偷摸摸的快速方法几乎不使用递归,因为找到最大值是一个微不足道的循环。
int largest(int arr[], int length) {
if (length <= 0) return INT_MIN;
int big = arr[0];
while (length > 1) {
int length_r = length / 2;
int length_l = length - length_r;
int big_r = largest(&arr[length_l], length_r);
if (big_r > big) big = big_r;
length = length_l;
}
return big;
}