如何写函数f(" 123")= 123 + 12 + 23 + 1 + 2 + 3作为递归关系

时间:2017-07-08 06:10:57

标签: algorithm math recursion numbers number-theory

我想知道是否有人可以帮我解决这个问题。

我希望f(str)获取一个数字字符串str,并将所有子字符串的总和作为数字返回,我想将f写为自身的函数,以便我可以尝试用memoization来解决这个问题。

当我盯着

时,它并没有向我跳出来
        Solve("1") = 1
        Solve("2") = 2
        Solve("12") = 12 + 1 + 2
        Solve("29") = 29 + 2 + 9
        Solve("129") = 129 + 12 + 29 + 1 + 2 + 9
        Solve("293") = 293 + 29 + 93 + 2 + 9 + 3
        Solve("1293") = 1293 + 129 + 293 + 12 + 29 + 93 + 1 + 2 + 9 + 3
        Solve("2395") = 2395 + 239 + 395 + 23 + 39 + 95 + 2 + 3 + 9 + 5
        Solve("12395") = 12395 + 1239 + 2395 + 123 + 239 + 395 + 12 + 23 + 39 + 95 + 1 + 2 + 3 + 9 + 5

3 个答案:

答案 0 :(得分:4)

您必须将f分解为两个函数。

N[i]成为输入的i位。设T[i]为输入的第一个i-1个字符的子串的总和。设B[i]为输入的第一个i字符的后缀之和。

因此,如果输入是" 12395",则B[3] = 9+39+239+1239T[3] = 123+12+23+1+2+3

复发关系是:

T[0] = B[0] = 0
T[i+1] = T[i] + B[i]
B[i+1] = B[i]*10 + (i+1)*N[i]

最后一行需要一些解释:第一个i+2字符的后缀是最后附加i+1的第一个N[i]个字符的后缀,以及单个字符的后缀-character string N[i]。这些的总和是(B[i]*10+N[i]*i) + N[i],与B[i]*10+N[i]*(i+1)相同。

另外f(N) = T[len(N)] + B[len(N)]

这提供了一个简短的线性时间迭代解决方案,您可以将其视为动态程序:

def solve(n):
    rt, rb = 0, 0
    for i in xrange(len(n)):
        rt, rb = rt+rb, rb*10+(i+1)*int(n[i])
    return rt+rb

print solve("12395")

答案 1 :(得分:3)

考虑这个问题的一种方法是考虑每个数字对最终总和的贡献。

例如,考虑数字Di中位置i(从结尾处)开始的数字xn-1…xi+1Diyi-1…y0。 (我使用xDy只是为了能够谈论数字位置。)如果我们查看包含D的所有子字符串并对它们进行排序通过数字末尾D的位置,我们将看到以下内容:

       D
      xD
     xxD
       …
   xx…xD
      Dy
     xDy
    xxDy
      …
  xx…xDy
     Dyy
    xDyy
   xxDyy
     …
 xx…xDyy

等等。

换句话说,对于从0到i(包括)的每个前缀长度,D出现在从0到n-i-1的每个位置,或者每个数字总共n-i次位置。这意味着它对总和的总贡献是从D*(n-i)100的10的幂的总和的10i倍。 (碰巧的是,这个总和恰好是(10i+1−1)⁄9。)

这导致了Paul Hankin提出的稍微简单的迭代版本:

def solve(n):
    ones = 0
    accum = 0
    for m in range(len(n),0,-1):
        ones = 10 * ones + 1
        accum += m * ones * int(n[m-1])
    return accum

通过以不同的方式重新排列总和,如果你真的想要一个递归解决方案,你可以提出这个简单的递归:

# Find the sum of the digits in a number represented as a string
digitSum = lambda n: sum(map(int, n))

# Recursive solution by summing suffixes:
solve2 = lambda n: solve2(n[1:]) + (10 * int(n) - digitSum(n))/9 if n else 0

如果不明显,10*n-digitSum(n)总是可被9整除,因为:

  1. 10*n == n + 9*n == (mod 9) n mod 9 + 0

  2. digitSum(n) mod 9 == n mod 9。 (因为10k == 1 mod n适用于任何k。)

  3. 因此(10*n - digitSum(n)) mod 9 == (n - n) mod 9 == 0

答案 2 :(得分:0)

看看这种模式:

Solve("1") = f("1") = 1
Solve("12") = f("12") = 1 + 2 + 12 = f("1") + 2 + 12 
Solve("123") = f("123") = 1 + 2 + 12 + 3 + 23 + 123 = f("12") + 3 + 23 + 123 
Solve("1239") = f("1239") = 1 + 2 + 12 + 3 + 23 + 123 + 9 + 39 + 239 + 1239 = f("123") + 9 + 39 + 239 + 1239
Solve("12395") = f("12395") = 1 + 2 + 12 + 3 + 23 + 123 + 9 + 39 + 239 + 1239 + 5 + 95 + 395 + 2395 + 12395 = f("1239") + 5 + 95 + 395 + 2395 + 12395

要获取新术语,n的长度为str,您可以在str中包含由基于0的索引字符范围组成的子字符串:{{ 1}}。

您可以编写一个函数来获取从子字符串索引范围形成的整数之和。调用该函数(n-1,n-1), (n-2,n-1), (n-3,n-1), ... (n-n, n-1),您可以在g(str)时以递归方式将函数写为f(str) = f(str.substring(0, str.length - 1)) + g(str),而str.length > 1的基本情况只返回str.length == 1的整数值。 (str的参数是substring中字符的起始索引和结果子字符串的长度。)

对于示例Solve(" 12395"),递归方程str得出:

f(str) = f(str.substring(0, str.length - 1)) + g(str)