我应该如何在没有反复试验的情况下解决这个递归
How should I go about solving this recursion without trial and error
int sum_down(int x)
{
if (x >= 0)
{
x = x - 1;
int y = x + sum_down(x);
return y + sum_down(x);
}
else
{
return 1;
}
}
参数 x 的最小整数值是多少,以便返回值大于 1.000.000 ?
现在我只是通过反复试验来做,因为这个问题是通过纸质格式提出的。我认为我没有足够的时间来反复试验。问题是,你们如何快速想象这个问题,以便可以轻松解决。谢谢大家,我是编程新手,所以提前感谢!
递归逻辑:
x = x - 1;
int y = x + sum_down(x);
return y + sum_down(x);
可以简化为:
x = x - 1;
int y = x + sum_down(x) + sum_down(x);
return y;
可以简化为:
int y = (x-1) + sum_down(x-1) + sum_down(x-1);
return y;
可以简化为:
return (x-1) + 2*sum_down(x-1);
以数学形式,
f(N) = (N-1) + 2*f(N-1)
递归在N
-1
时终止。 f(-1)
= 1
.
因此
f(0) = -1 + 2*1 = 1
f(1) = 0 + 2*1 = 2
f(2) = 1 + 2*2 = 5
...
f(18) = 17 + 2*f(17) = 524269
f(19) = 18 + 2*524269 = 1048556
你的程序可以这样写(对不起 c#(:
public static void Main()
{
int i = 0;
int j = 0;
do
{
i++;
j = sum_down(i);
Console.Out.WriteLine("j:" + j);
} while (j < 1000000);
Console.Out.WriteLine("i:" + i);
}
static int sum_down(int x)
{
if (x >= 0)
{
return x - 1 + 2 * sum_down(x - 1);
}
else
{
return 1;
}
}
所以在第一次迭代时,你会得到 2,然后是 5,然后是 12...因此,您可以忽略 x-1 部分,因为与乘法相比,它会保持很少。
所以我们有:
i = 1 => sum_down ~= 4 (real is 2)
i = 2 => sum_down ~= 8 (real is 5)
i = 3 => sum_down ~= 16 (real is 12)
i = 4 => sum_down ~= 32 (real is 27)
i = 5 => sum_down ~= 64 (real is 58)
所以我们可以说sum_down(x( ~= 2^x+1。然后它只是基本的数学,2^x+1 <1 000 000,即 19。
有点晚了,但获得一个精确的非递归公式并不难。
用数学方式写出来,正如其他答案中所解释的那样:
f(-1) = 1
f(x) = 2*f(x-1) + x-1
这与
f(-1) = 1
f(x+1) = 2*f(x) + x
(刚刚从 x 和 x-1 切换到 x+1 和 x,两种情况下的差异均为 1(
前几个 x 和 f(x( 是:
x: -1 0 1 2 3 4
f(x): 1 1 2 5 12 27
虽然有许多任意复杂的方法可以将其转换为非递归公式,但使用简单的方法,通常有助于写出每个两个元素之间的区别:
x: -1 0 1 2 3 4
f(x): 1 1 2 5 12 27
0 1 3 7 15
所以,对于某些 x
f(x+1) - f(x) = 2^(x+1) - 1
f(x+2) - f(x) = (f(x+2) - f(x+1)) + (f(x+1) - f(x)) = 2^(x+2) + 2^(x+1) - 2
f(x+n) - f(x) = sum[0<=i<n](2^(x+1+i)) - n
例如插入一个x=0
,使f(x+n)
f(n)
:
f(x+n) - f(x) = sum[0<=i<n](2^(x+1+i)) - n
f(0+n) - f(0) = sum[0<=i<n](2^(0+1+i)) - n
f(n) - 1 = sum[0<=i<n](2^(i+1)) - n
f(n) = sum[0<=i<n](2^(i+1)) - n + 1
f(n) = sum[0<i<=n](2^i) - n + 1
f(n) = (2^(n+1) - 2) - n + 1
f(n) = 2^(n+1) - n - 1
不再递归。
这个怎么样:
int x = 0;
while (sum_down(x) <= 1000000)
{
x++;
}
循环递增 x,直到 sum_down(x( 的结果优于 1.000.000。
编辑:结果将是 19。
虽然试图理解和简化sum_down()
函数背后的递归逻辑是有启发性和信息性的,但这个片段往往是合乎逻辑和实用的,因为它不是试图从上下文的角度解决问题,而是在结果方面。
两行 Python 代码来回答你的问题:
>>> from itertools import * # no code but needed for dropwhile() and count()
定义递归函数(参见R Sahu的答案(
>>> f = lambda x: 1 if x<0 else (x-1) + 2*f(x-1)
然后使用 dropwhile()
函数从列表 [0, 1, 2, 3, ....] 中删除f(x)<=1000000
的元素,从而生成一个f(x) > 1000000
的整数列表。注意:count()
返回 [0, 1, 2, ....( 的无限"列表">
dropwhile()
函数返回一个 Python 生成器,因此我们使用 next()
来获取列表的第一个值:
>>> next(dropwhile(lambda x: f(x)<=1000000, count()))
19
- 如何在不使用额外空间的情况下解决这个问题?
- 如何解决在负数的情况下程序以相同方式工作的问题?
- 在这种情况下,我们可以使用静态而不是朋友吗,还有其他解决方案是什么
- 如何在不设置 ulimit -n 的情况下解决套接字程序打开太多文件的错误
- 如何在不创建新配置的情况下对两个不同解决方案使用的一个项目使用不同的 #defines
- 模板和unique_ptr继承情况下的重载解决方案
- 在这种情况下如何解决?语法错误:在"* "node" ?
- Boost Filesystem flowly_caronical不会在没有父文件夹的情况下解决相对路径
- 解决方案重新生成在 30% 的情况下失败
- 在这种情况下,有没有办法用单个解决方案替换两个仅在类型上不同的相似函数?
- 如何在没有System32的情况下解决"java.lang.UnsatisfiedLinkError:找不到依
- 错误:在没有参数列表的情况下无效使用模板名称“ExTree” ||如果解决这个问题怎么办?(初学者)
- 在这种情况下如何解决"Reference to non-static member function must be called"?
- 我的项目如何在没有提示的情况下不抱怨未解决的未支出
- 我如何在不将所有相关代码带到标头的情况下解决模板成员函数的未定义引用
- 这个错误一般意味着什么?以及在这种情况下我如何解决它
- 如何在没有数据库的情况下解决这3个用例
- 我应该如何在没有反复试验的情况下解决这个递归
- 将int转换为void*会丢失精度,在需要的情况下解决方案是什么
- 循环包含,如何在不更改类层次结构的情况下解决此问题