我想知道是否有人可以帮我解决这个问题。
我希望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
答案 0 :(得分:4)
您必须将f
分解为两个函数。
让N[i]
成为输入的i
位。设T[i]
为输入的第一个i-1
个字符的子串的总和。设B[i]
为输入的第一个i
字符的后缀之和。
因此,如果输入是" 12395",则B[3] = 9+39+239+1239
和T[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
。 (我使用x
,D
和y
只是为了能够谈论数字位置。)如果我们查看包含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整除,因为:
10*n == n + 9*n == (mod 9) n mod 9 + 0
digitSum(n) mod 9 == n mod 9
。 (因为10k == 1 mod n
适用于任何k
。)
因此(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)