好的,我知道这听起来像是家庭作业;但这有任何办法。我正在尝试使用C#解决此问题problem。问题描述的摘录如下所示:
给定输入n,可以确定数字的数量 印刷(包括1)。对于给定的n,这被称为 循环长度n。在上面的例子中,循环长度22是16。 对于任何两个数字i和j,您将确定i和j之间所有数字的最大循环长度。
除了一件事,我知道一切,周期长度。我完全不明白。我发现文本的定义含糊不清。我假设,循环长度是序列中的数字,所以假设输入为10,循环长度为8.但我只是不确定。您不需要代码,但我只能提供指导。
此外,我已经知道如何从标准输入和输出中读取。由于问题在于编程竞争格式。
static void collatz(ref int n)
{
if (n % 2 == 0)
{
n /= 2;
}
else
{
n = (3 * n) + 1;
}
Console.WriteLine(n);
}
static int GetCycleLength(int n)
{
if (n > 0)
{
int count = 1;
while (n != 1)
{
collatz(ref n);
count++;
}
return count;
}
else
{
return -1;
}
}
虽然不是作业,但我想把它作为家庭作业,所以我把它作为标签之一。
答案 0 :(得分:3)
您应该使用动态编程。也就是说,如果你为数字j工作并且在为j工作时遇到k。那么你不应该再次重复k的整个工作。
从j开始,然后去找我。假设您正在查找数字n的循环长度。在找到n的循环长度时,假设您遇到数字:n,n8,n7,n6,...,n1。然后循环长度为n为9,对于n8为8,对于n7为7.存储数组或映射中所有此类数字的循环长度。当您遇到相同的数字以查找任何不同数字的周期长度时,可以随处重用它们。这将为您提供解决此问题的最佳解决方案。
请参阅http://en.wikipedia.org/wiki/Dynamic_programming#Fibonacci_sequence
的动态编程示例答案 1 :(得分:2)
循环长度是算法必须应用于原始自然数/整数以便最终达到1的次数。
示例,如果您从7开始:
我们已将算法 16 应用于数字7,我们得到1.因此,16是周期长度。
代码效果提示 -
您可以使用按位运算,而不是在collatz(ref int n)
中进行乘法和除法。这将使性能得到显着提升。
答案 2 :(得分:1)
对于特定的起始值(n
),循环长度只是达到1所需的数量(包括最后的1)。对于10
:
10 5 16 8 4 2 1
因此周期长度为7。
因此,对于此问题,您必须从i
循环到j
,确定迭代的每个整数的循环长度,并返回遇到的最大循环长度。您可能希望查看另一个答案所提到的dynamic programming(即存储先前计算的周期长度,然后在将来的计算中使用这些存储的值)。
答案 3 :(得分:0)
所提到的案文对周期长度的定义并不含糊不清;它说:“给定输入n,可以确定打印的数字...对于给定的n,这称为循环长度n”。例如,给定输入20,参考过程打印出20 10 5 16 8 4 2 1
,因此“周期长度为20”为8.在某种意义上,您的程序模拟 n ,查找并打印遇到的最大周期长度。
注意,使用动态编程的建议可能会有些误导。您实际可以使用的是 memoization ,即记录以前处理过的输入的全部或部分结果。记录结果很麻烦,所以如果你的程序足够快而没有记忆,那么就不要费心了。问题是假设“没有操作溢出32位整数”。如果您不做进一步的假设并记录所有中间结果,则需要一个能够处理数十亿个不同值的字典数据结构。如果您对最大循环长度做出假设,则程序可能会失败。无论如何,一种方法是选择一些大数K并分配一个整数数组M;将数组初始化为全零,M[1] = 1
除外。在Collatz例程中,每次执行步骤4(即 n←3n + 1)时,将1推入一堆位。 (堆栈中的位数应不小于最大循环长度。)每次执行步骤5(即 n←n / 2)时,将0推入堆栈。
如果您在任何步骤中找到M[n] > 0
,那么您知道您已经将n的周期长度计算为c = L = M[n]
。此时,您可以展开位堆栈并返回L.在展开后,在每次弹出后,如果您弹出0,则计算n
(如n = 2*n
;如果您弹出0,则计算n = (n-1)/3
弹出1),执行++c
,如果n<K
设置M[n] = c
。