2递归方程 - 寻找指数

时间:2014-12-18 12:39:58

标签: python recursion relationship recurrence

我在确定下面给出的2个递归关系之间的关系时遇到了一些麻烦。

f(0) = 1  
f(1) = 1  
f(2) = 2  
f(2n) = f(n) + f(n + 1) + n          (for n > 1)  
f(2n + 1) = f(n - 1) + f(n) + 1      (for n >= 1)

所以这个系列就像:(索引:0,1,2,3 ...... n)
1,1,2,3,7,4,13,6,15,11,22,12,25,18,28,20,34 ......

目标是找到系列中任何给定数字出现的索引 例如:
鉴于:7
输出:4即f(4)= 7

此外,由于可能在给定序列中出现多次,因此返回上次该数字。
例如:
鉴于:22
这里,f(10)= 22和f(17)= 22
所以,输出:17

从python代码 - 我发现一个数字最多发生两次(虽然不是100%肯定..)。

我的代码可以找到系列中的第n个数字:

memo = {}
def rep(k):
    if k<=1:
        return 1
    if k == 2:
        return 2
    if not k in memo:
        if k%2==0:
            memo[k] = (k/2) + rep((k/2)+1) + rep(k/2)
        else:
            memo[k] = 1 + rep(((k-1)/2)-1) + rep((k-1)/2)
    value_key[memo[k]] = k
    return memo[k]

我使用memo来散列我已经生成的值,但是使用这种方法生成并尝试从0开始的数字,直到我得到一个等于给定数字的值(简单的暴力)需要永远,并导致MemoryErrors更大的数字(输入将从1到20位数。)

那么,我失踪的给定方程之间是否存在任何关系? 如果我能找到f(n)(给定输入)和n之间的关系 - 我认为它可以很容易地在代码中实现,但我无法用数学方式简化它 - 我尝试过替换一个接一个(给定的复发关系),但到目前为止,我无法弄清楚任何事情。

1 个答案:

答案 0 :(得分:0)

编辑:

现在使用二进制搜索最接近的值以及memoization,需要测试,但这个想法很简单。这仍然依赖于evenodd正在增加序列的事实。

#!/usr/bin/env python

# inspired by your code
memo = {'even': {0: 1, 2: 2}, 'odd': {1: 1}}


def f(k):
    if k in memo['even']:
        return memo['even'][k]
    if k in memo['odd']:
        return memo['odd'][k]
    else:
        if k % 2 == 0:
            memo['even'][k] = (k / 2) + f((k / 2) + 1) + f(k / 2)
        else:
            memo['odd'][k] = 1 + f(((k - 1) / 2) - 1) + f((k - 1) / 2)
    return f(k)

# binary search on even values
def seek_even(x):
    left = 0
    right = f(x)
    if right % 2 != 0:
        right += 1
    middle = (right - left) / 2
    if middle % 2 != 0:
        middle += 1
    while f(middle) != x and left < middle < right:
        if f(middle) < x:
            left = middle
        else:
            right = middle
        middle = (left + right) / 2
        if middle % 2 != 0:
            middle += 1
    return middle

# binary search on odd values
def seek_odd(x):
    left = 1
    right = x
    if right % 2 == 0:
        right += 1
    middle = (right - left) / 2
    if middle % 2 == 0:
        middle += 1
    while f(middle) != x and left < middle < right:

        if f(middle) < x:
            left = middle
        else:
            right = middle
        middle = (left + right) / 2
        if middle % 2 == 0:
            middle += 1
    return middle


def seek(x):
    indices = [seek_even(x), seek_odd(x)]
    print "closest indices: " % indices
    return max(filter(lambda c: f(c) == x, indices) + [-1])

tests = [264227, 22, 10, 100000000000000000000, 31]
for i in tests:
    print "seek range [0, %d] for %d" % (f(i), i), seek(i)