我有一个字符列表,比如x,用b[1], b[2], b[3] ... b[x]
表示。在x
之后,
b[x+1]
是此订单中b[1],b[2].... b[x]
的串联。同样,
b[x+2]
是b[2],b[3]....b[x],b[x+1]
的串联。
所以,基本上,b[n]
将是x
的{{1}}个术语的连接,从右边开始。
将参数b[i]
和p
作为查询,如何找出q
中b[1], b[2], b[3]..... b[x]
th q
的字符对应于?
注意: b[p]
和x
已针对所有查询修复。
我尝试过强制但是字符串长度对于大x来说呈指数级增长。(x <= 100)。
示例:
b[1], b[2], b[3]..... b[x]
,
x=3
因此,对于b[] = a, b, c, a b c, b c abc, c abc bcabc, abc bcabc cabcbcabc, //....
//Spaces for clarity, only commas separate array elements
,p=7
的查询,返回的答案为q=5
(对应于字符3
)。
我很难搞清楚它背后的数学。语言没有问题
答案 0 :(得分:1)
当我弄清楚时,我写了这个答案,所以请耐心等待。
正如您所提到的,更容易找出b[p][q]
中的字符来自原始x
字符的位置,而不是为大b[p]
生成p
。为此,我们将使用循环查找当前b[p][q]
的来源,从而减少p
,直到介于1
和x
之间,q
直到它是1
。
让我们看一下x=3
的示例,看看我们是否可以得到一个公式:
p N(p) b[p]
- ---- ----
1 1 a
2 1 b
3 1 c
4 3 a b c
5 5 b c abc
6 9 c abc bcabc
7 17 abc bcabc cabcbcabc
8 31 bcabc cabcbcabc abcbcabccabcbcabc
9 57 cabcbcabc abcbcabccabcbcabc bcabccabcbcabcabcbcabccabcbcabc
序列清晰:N(p) = N(p-1) + N(p-2) + N(p-3)
,其中N(p)
是b
的第p个元素中的字符数。给定p
和x
,您可以强制计算范围N
的所有[1, p]
。这样您就可以确定b
b[p][q]
的先前元素来自哪个。
为了说明,请说x=3
,p=9
和q=45
。
N(6)=9
,N(7)=17
和N(8)=31
。自45>9+17
起,您知道b[9][45]
来自b[8][45-(9+17)] = b[8][19]
。19>9+5
,b[8][19] = b[7][19-(9+5)] = b[7][5]
。5>N(4)
但5<N(4)+N(5)
,b[7][5] = b[5][5-3] = b[5][2]
。b[5][2] = b[3][2-1] = b[3][1]
3 <= x
起,我们有终止条件,b[9][45]
c
来自b[3]
。从p
,q
,x
和b
到x
开始,可以非常容易地递归计算或迭代计算这样的事情。我的方法需要p
个数组元素来计算整个序列的N(p)
。如果以递归方式工作,可以在数组或堆栈中分配。
这是vanilla Python中的参考实现(没有外部导入,虽然numpy可能有助于简化这一点):
def so38509640(b, p, q):
"""
p, q are integers. b is a char sequence of length x.
list, string, or tuple are all valid choices for b.
"""
x = len(b)
# Trivial case
if p <= x:
if q != 1:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
return p, b[p - 1]
# Construct list of counts
N = [1] * p
for i in range(x, p):
N[i] = sum(N[i - x:i])
print('N =', N)
# Error check
if q > N[-1]:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
print('b[{}][{}]'.format(p, q), end='')
# Reduce p, q until it is p < x
while p > x:
# Find which previous element character q comes from
offset = 0
for i in range(p - x - 1, p):
if i == p - 1:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
if offset + N[i] >= q:
q -= offset
p = i + 1
print(' = b[{}][{}]'.format(p, q), end='')
break
offset += N[i]
print()
return p, b[p - 1]
调用so38509640('abc', 9, 45)
生成
N = [1, 1, 1, 3, 5, 9, 17, 31, 57]
b[9][45] = b[8][19] = b[7][5] = b[5][2] = b[3][1]
(3, 'c') # <-- Final answer
同样,对于问题中的示例,so38509640('abc', 7, 5)
会产生预期结果:
N = [1, 1, 1, 3, 5, 9, 17]
b[7][5] = b[5][2] = b[3][1]
(3, 'c') # <-- Final answer
抱歉,我无法想出一个更好的函数名称:)这是一个非常简单的代码,它应该在Py2和3中同样有效,尽管range
函数/类有差异。
我很想知道是否存在针对此问题的非迭代解决方案。也许有一种方法可以使用模运算或其他方式......