这应该是非常基本的。 我觉得我缺少明显的东西,但是我已经盯着它看了一段时间了。 我有一个创建Collatz序列的递归方法(用作递归实践) 但是,一旦我的方法达到退出要求,我就会有一个“返回值”,然后返回到该方法内的递归调用。 如果有人能告诉我我想念的东西,我将不胜感激! 谢谢,下面的代码!
public int sequenceCreator(int currentVal, int numOfSteps)
{
int nextVal;
while (currentVal != 1)
{
if (currentVal % 2 == 0)
{
nextVal = currentVal / 2;
numOfSteps++;
}
else // (currentVal % 2 > 0)
{
nextVal = (currentVal * 3) + 1;
numOfSteps++;
}
return sequenceCreator(nextVal, numOfSteps);
}
return numOfSteps;
}
答案 0 :(得分:0)
return
仅退出该特定方法调用。它并不会终止调用sequenceCreator()
的所有时间。
在这种情况下,应该可以,因为它会返回到此行:
return sequenceCreator(nextVal, numOfSteps);
依次返回到其调用者,依此类推,直到最终解决所有递归调用。
但是我可以这样写方法:
public int sequenceCreator(int currentVal)
{
if (currentVal == 1) return 1;
if (currentVal % 2 == 0)
{
return 1 + sequenceCreator(currentVal / 2);
}
else // (currentVal % 2 > 0)
{
return 1 + sequenceCreator(currentVal * 3 + 1);
}
}
对于相同的输入,该代码会产生相同的结果,但是使用更少的代码却更易于理解,并且不需要在方法调用之间传递额外的状态。
为了好玩,我们可以使用三元运算符进一步减少代码(但由于imo可读性差,我不建议使用此版本):
public int sequenceCreator(int currentVal)
{
if (currentVal == 1) return 1;
return 1 + sequenceCreatetor(currentValue % 2 == 0? currentVal / 2 : currentVal * 3 + 1);
}
我显示此版本以说明为什么使用 递归。从本质上讲,递归问题就是堆栈问题。对于每个递归解决方案,都有一个匹配解决方案,该解决方案仅依赖于传统方法,而是使用堆栈(递归解决方案仅依靠程序的调用堆栈来“隐藏”堆栈)。但是,对于某些类型的问题,递归可以大大减少解决该问题所需的代码量。因此,我们也有相反的说法。如果您发现自己使用堆栈,则可以使用 来大大简化问题。在这种情况下,方法主体只有两行,如果我真的愿意,我可以将其简化为一行代码。
您还需要了解,此操作不会创建序列。在完全收敛的情况下,它会创建一个恰好一个值。如果您实际上要创建一个序列,则需要返回一个IEnumerable
,最好使用yield
关键字:
public IEnumerable<int> sequenceCreator(int currentVal)
{
if (currentVal == 1) yield return 1;
if (currentVal % 2 == 0)
{
yield return 1 + sequenceCreator(currentVal / 2);
}
else // (currentVal % 2 > 0)
{
yield return 1 + sequenceCreator(currentVal * 3 + 1);
}
}
从逻辑上讲,我认为您在这里很安全,并且会收敛。此方法的“最终”或基本情况是1
的输入。在基本情况下调用甚至减少输入的位置。输入为奇数的调用从基本情况开始增加,但以这种方式使下一个输入始终为偶数,并且始终与我们之前尝试的值不同。最终,我们希望以2的幂或3的2的幂结束,即使将其减小到3
或2
,然后是{{1} },然后退出。
但是,我担心可能存在一些永远不会达到此状态的值,或者在它们可以溢出之前溢出整数,或者在增加几次之后减小到我们已经拥有的均匀值尝试,从而创造了一个永无止境的循环。
答案 1 :(得分:-1)
我认为不应有任何循环。使用if条件而不是while。
如果(currentVal!= 1)
答案 2 :(得分:-2)
如果可能,请避免递归:
int sequenceNumber = Convert.ToInt32(Console.ReadLine());
List<int> list = new List<int>();
while (sequenceNumber>=1)
{
if (sequenceNumber == 1)
{
Console.WriteLine(1);
sequenceNumber = Convert.ToInt32(Console.ReadLine());
}
else if(sequenceNumber>1)
{
while (sequenceNumber>=1)
{
if (sequenceNumber == 1)
{
list.Add(sequenceNumber);
}
else if (sequenceNumber % 2 == 0)
{
list.Add(sequenceNumber);
sequenceNumber = sequenceNumber / 2;
}
else if (sequenceNumber % 2 != 0)
{
list.Add(sequenceNumber);
sequenceNumber = sequenceNumber * 3 + 1;
}
}
list.ForEach(Console.WriteLine);
foreach (int i in list)
{
Console.Write(i + " ");
}
}
sequenceNumber = Convert.ToInt32(Console.ReadLine());
}
}