2015-11-04 123 views
2

我正在练习解决递归类的问题。我的解决方案递归吗? (学习递归)

我解决此站点上的问题:http://www.w3resource.com/javascript-exercises/javascript-recursion-functions-exercises.php

的问题我指的是规定:编写JavaScript程序来获取整数的范围(X,Y)。 实施例:范围(2,9) 预期输出:[3,4,5,6,7,8]

之前看溶液我提出了这样的:

var range = function (start, end) { 
    var result = []; 
    var accumulator = start; 

    var accumulate = function() { 
    accumulator++; 
    if (accumulator === end) { 
     return; 
    } else { 
     result.push(accumulator); 
    } 
    accumulate(); 
    }; 

    accumulate(); 
    return result; 
}; 

将溶液在网站上是这样的:

var range = function(start_num, end_num) 
{ 
    if (end_num - start_num === 2) 
    { 
    return [start_num + 1]; 
    } 
    else 
    { 
    var list = range(start_num, end_num - 1); 
    list.push(end_num - 1); 
    return list; 
    } 
}; 

我的解决方案在技术上仍然递归吗?最近我有一个类似的测验答案,我被告知我的解决方案基本上是迭代的。

+0

正如在某些答案中指出的那样,您的递归函数可以很容易地重写为循环。递归函数的好例子是除法和征服算法,比如快速排序,其中问题的子集通过函数递归地传递给自己作为参数。如果你不熟悉,那么查找分治算法是值得的。 – element11

回答

3

尽管您使用递归,但您只是以递归的形式编写了一个循环。

我打算从纯粹的学术观点来回答这个问题。如果你想避免中间状态(result),并使用纯功能性的结构,我会写这样

function range(start, end) { 
    function recRange(current, end) { 
    if (current > end) 
     return []; 
    return [current].concat(recRange(current + 1, end)); 
    } 
    return recRange(start + 1, end - 1); 
} 
console.log(range(2, 9)); 
// [ 3, 4, 5, 6, 7, 8 ] 

如果你看到这里,我们创建了range功能,递归创建一个新的中的新功能数组在每次迭代(记住:这不是高性能的代码,你可以简单地使用循环,并有效地解决这个问题)。

递归的基本条件是current < end。一旦满足,递归停止并返回一个空数组。在所有级别中,具有current值的新数组与递归调用的结果连接在一起。因此,呼叫的评价大致了解这样

[3].concat(recRange(3 + 1, end)); 
[3].concat([4].concat(recRange(4 + 1, end))); 
... 

末,当递归解开,该值将是这样的

[3].concat([4].concat([5].concat([6].concat([7].concat([8].concat([])))))) 
[3].concat([4].concat([5].concat([6].concat([7].concat([8]))))) 
[3].concat([4].concat([5].concat([6].concat([7, 8])))) 
[3].concat([4].concat([5].concat([6, 7, 8]))) 
[3].concat([4].concat([5, 6, 7, 8])) 
[3].concat([4, 5, 6, 7, 8]) 
[3, 4, 5, 6, 7, 8] 

,并且将作为结果返回。

2

我的解决方案在技术上仍然是递归的吗?

是。你正在使用尾递归;然而,由于没有任何参数被传递到accumulate(),我可以看到为什么有人会说它基本上是迭代的。您可以轻松地用循环替换递归调用。递归算法通常利用堆栈。

由于Javascript的关闭,与其他语言(如C++或Java或C#)相比,很难理解JavaScript中的递归概念。

要理解递归,您必须先了解递归。 :)

2

为了让您的解决方案递归的,它应该返回一些价值并以某种方式结合递归调用的结果形成原始调用的返回值。

让我说明了一个例子,通过修改您的解决方案:

var range = function (start, end) { 

    var accumulate = function (accumulator) { 
    if (accumulator === end - 1) { 
     return [accumulator]; // Stop condition 
    } else { 
     // Recursive block 
     var result = accumulate(accumulator+1); // recursive call 
     result.unshift(accumulator); // combine result 
     return result 
    } 
    }; 

    return accumulate(start); 
}; 

修改后的累积函数将返回一个元素列表的停止条件,它处理最简单的情况下,当蓄电池到达最后一个值返回。

在示例range(2,9)中,停止条件将返回[8]

然后在主叫方,递归块

 var result = accumulate(accumulator+1); 
     result.unshift(accumulator); 
     return result 

将采取列表[8],并preprend的accumulator7)的电流值,所以它会返回[7,8]

...和accumulator(7)调用者,将获得[7,8]和值6 preprend到列表,返回[6,7,8]

最后,原来致电accumulator(2)的电话会产生预期结果[2,3,4,5,6,7,8]