在这里,我有两种解决方案可以找到一个是否是一个回文。第一个使用递归,第二个使用循环。我很困惑我的代码与递归会如何执行而没有递归的代码。具有递归的代码是否在O(n)时间内运行?如果是这样,怎么样?
//Solution using recursion
function isPalindrome(arr) {
//Runs on first call only
if (typeof arr === "string"){
//remove whitespace
if(arr.match(/\s/)) {
arr = arr.replace(/\s/g, "");
}
//convert to array
arr = arr.split("");
}
//base condition
if(arr.length === 0 || arr.length === 1) {
//console.log(true);
return true;
} else {
if (arr[0] !== arr[arr.length - 1]) {
//console.log(false);
return false;
} else {
arr.shift(); //remove first element
arr.pop(); //remove last element
//recursive call
isPalindrome(arr);
}
}
}
//Solution without using recursion
function palindrome(str) {
var reverseString = [];
//remove whitespace
if(str.match(/\s/)) {
str = str.replace(/\s/g, "");
}
//convert to array
var arr = str.split("");
for(var i = arr.length; i > 0; i--) {
reverseString.push(arr.pop());
}
if (reverseString.join("") === str) {
return true;
} else {
return false;
}
}
console.log(palindrome("racecar"));
console.log(palindrome("si racecar is"));
答案 0 :(得分:3)
回答你的标题问题:
不,递归不会提高性能。它可能总是使实现更慢(与相同的基于循环的对应物相比)
关于复杂性:
您的递归解决方案很可能是O(n^2)
,因为arr.shift()
操作可能是线性的。
自V8实施以来:array.shift
操作 是线性的。请参阅https://github.com/v8/v8/blob/master/src/array.js#L596和https://github.com/v8/v8/blob/master/src/array.js#L313
替代实施:
function isPalindromeZ(s) {
for (var i = 0, len = s.length; i < len / 2; ++i) {
if (s[i] != s[len - i - 1]) {
return false;
}
}
return true;
}
与您的实现相比,此实现的好处在于额外内存消耗为O(1)
。
答案 1 :(得分:1)
不,递归本身并不能提高性能,反之亦然。递归调用会增加一些开销,因此递归解决方案通常比迭代解决方案慢一些,如果存在一个简单解决方案(如示例中所示)。
递归可用于简化嵌套在自然界中的某些任务,这些任务需要迭代地解决复杂的代码。在这种情况下,递归可以提高性能,通过消除如此多的复杂性,它远远超过它增加的小开销。
您的问题中的示例不是如何使用递归的一个很好的示例。它可用于演示递归的工作原理,但无法证明递归的使用方式。
递归版本没有O(n)复杂度,更接近O(n²)复杂度。 arr.shift()
调用将移动数组中的所有项,这意味着每次迭代都有一个内部循环,它运行剩余数组的长度。
此外,递归版本中存在错误;最后一行应该是:
return isPalindrome(arr);