我想为
this question写一个回溯解决方案,要求找到总和给定n的最明显的奇数.
我把这个Python代码整合在一起:
import sys
sys.setrecursionlimit(10000)
stop = False
def solve(n, used, current_sum):
global stop
if stop:
return
if current_sum == n:
print(used)
stop = True
return
start = 1 if len(used) == 0 else (used[-1] + 2)
for i in range(start, n + 1, 2):
if current_sum + i <= n and not stop:
used.append(i)
solve(n, used, current_sum + i)
used.pop()
else:
return
solve(100000000, [], 0)
遗憾的是,它不会为我打印任何内容.据我所知,如果有条件,它永远不会达到.如果我在每一步打印current_sum,当整个程序退出没有错误时,它似乎停在16000000左右.
我试过增加递归限制,没有运气.
我在Windows 8.1下在Idle和Eclipse上测试了它,在Python 3.4中,64位.我有16 GB的RAM.
如果我减少n,那么我得到一个解决方案(例如删除一个零).
这对我来说没有意义,所以我想看看我是否有更好的运气C.我在C中攻击了这个:
int sol[100000];
bool done = false;
void solve(int n, int k, int sum)
{
if (done)
return;
if (sum == n)
{
done = true;
for (int i = 0; i < k; ++i)
{
printf("%d ", sol[i]);
}
printf("\n");
return;
}
int start = 1;
if (k > 0)
start = sol[k - 1] + 2;
for (int i = start; i <= n; i += 2)
if (sum + i <= n && !done)
{
sol[k] = i;
solve(n, k + 1, sum + i);
}
else
return;
}
int main()
{
solve(100000000, 0, 0);
return 0;
}
即使我添加另一个零,哪个效果很好!
与Python有什么关系?我如何才能使这个值适用于大值?
较低值的执行时间与C代码相当,它只是让我退出更高的值.
最佳答案
What is the deal with Python and how can I get this working for large
values as well?
我重写了你的代码以使它工作.增加n参数时,需要调整递归深度.我使用Python 2.7.6.我们的想法是和你编写的C代码一样,传递的第二个参数是整数,而不是列表.
import sys
sys.setrecursionlimit(100000)
sol = []
stop = False
def solve(n, k, current_sum):
global stop
if stop:
return
if current_sum == n:
stop = True
for i in xrange(0, k, 1):
print(sol[i]),
print
return
start = 1 if len(sol) == 0 else (sol[k-1] + 2)
for i in xrange(start, n + 1, 2):
if current_sum + i <= n and not stop:
sol.append(0)
sol[k] = i
solve(n, k + 1, current_sum + i)
else:
return
solve(100000000, 0, 0)
讨论这个问题
我试着读你编写的python代码的内存使用情况.我必须设置n = 100.000才能获得370 MB的结果.添加0使我的操作系统终止程序. (在Mac OS X上,我收到内存错误).
这是我在Linux上使用的代码:
import os
import sys
sys.setrecursionlimit(100000)
_proc_status = '/proc/%d/status' % os.getpid()
_scale = {'kB': 1024.0, 'mB': 1024.0*1024.0,
'KB': 1024.0, 'MB': 1024.0*1024.0}
def _VmB(VmKey):
'''Private.
'''
global _proc_status, _scale
# get pseudo file /proc/<pid>/status
try:
t = open(_proc_status)
v = t.read()
t.close()
except:
return 0.0 # non-Linux?
# get VmKey line e.g. 'VmRSS: 9999 kB\n ...'
i = v.index(VmKey)
v = v[i:].split(None, 3) # whitespace
if len(v) < 3:
return 0.0 # invalid format?
# convert Vm value to bytes
return float(v[1]) * _scale[v[2]]
def memory(since=0.0):
'''Return memory usage in bytes.
'''
return _VmB('VmSize:') - since
stop = False
def solve(n, used, current_sum):
global stop
if stop:
return
if current_sum == n:
print(used)
stop = True
return
start = 1 if len(used) == 0 else (used[-1] + 2)
for i in range(start, n + 1, 2):
if current_sum + i <= n and not stop:
used.append(i)
solve(n, used, current_sum + i)
used.pop()
else:
return
m0 = memory()
solve(100000, [], 0)
m1 = memory(m0)
print(m1/(1024*1024))
与此结果相比,我编写的改进(更正)代码仅使用4 MB,参数n设置为100.000.000.这确实是一个巨大的差异.
我不确定为什么会这样.特别是你有一个包含递归调用的循环(所以你可以从同一个分支中多次递归调用).
如果你坚持使用递归调用,那么也许你想重新设计你的程序.具有记忆功能的递归调用可能比情况下的循环更快.见this link for example.