我的代码有问题。这不是工作或家庭作业。我只想了解递归函数。代码首先工作,但是当它找到一个超过22000个字符的单词时,它会导致抛出错误 - stackoverflowexception。
这是代码
using System;
namespace Palindrome
{
using System.IO;
public class Program
{
public static void Main()
{
int c = 0;
string[] l = File.ReadAllLines("UKACD17.TXT");
for (int i = 0; i < l.Length; i++)
{
string ll = l[i];
if (T(ll))
{
Console.WriteLine(ll);
c++;
}
}
Console.WriteLine("Found {0} palindromes.", c);
Console.ReadLine();
}
private static bool T(string s)
{
if (string.IsNullOrWhiteSpace(s)) return false;
return s.Length == 1 || (s[0] == s[s.Length - 1] && T(s.Substring(1, s.Length - 2)));
}
}}
答案 0 :(得分:1)
该方法看起来在逻辑上是正确的,但由于执行代码的计算机存在实际限制,因此无法正常工作。
每当你调用一个方法时,它都会将调用方法的状态推送到一个堆栈上 - 基本上是一个包含数据的内存块,一旦被调用的方法执行完毕,这将允许执行在调用方法中继续执行。
这个内存块是非常小的,所以如果你试图递归地调用11000次方法(对于一个22000个字符的初始输入),那就需要推送11000个堆栈帧 - 这显然是一种方式比允许的更深的递归(并且它可能在11000之前很久就会放弃)。
我想,限制已设定,因为否则会耗尽有限的内存,可用于其他更有用的内容。
不是递归地调用该方法,而是可以将其转换为循环:
private static boolean T(string s) {
if (string.IsNullOrWhiteSpace(s)) return false;
int i = 0;
int j = s.length - 1;
while (i < j) {
if (s[i] != s[j]) return false;
i++; j--;
}
return true;
}
这使用两个指向你移动的字符串的指针 - 在每一步,如果它们指向不同的字符,它就不能成为回文,所以你可以返回false;否则,将它们朝向对方移动并重复。
调用它要便宜得多,因为不需要推送堆栈帧 - 你所做的就是比较字符并递增/递减几个整数。