我有一个字符列表,比如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]将是b [i]的最后x项的连接,从右边开始.
>给出p和q作为查询的参数,如何找出b [1],b [2],b [3]中的哪个字符….. b [x]确定b [p]的第q个字符对应?
注意:对于所有查询,x和b [1],b [2],b [3] ….. b [x]是固定的.
我尝试了强制执行,但是对于大的x,字符串长度呈指数增长.(x <= 100). 例:
>当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(对应于字符’c’).
我只是很难搞清楚它背后的数学.语言没有问题
最佳答案 当我想出来的时候,我写下了这个答案,所以请耐心等待.
正如你所提到的,更容易找出b [p] [q]中的字符来自原始x字符而不是为大p生成b [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,你可以蛮力计算范围[1,p]的所有N.这将允许您找出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 > b [5] [2] = b [3] [2-1] = b [3] [1]
>由于3 <= x,我们有终止条件,而b [9] [45]是来自b [3]的c.
在开始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中同样有效,尽管范围函数/类有差异.
我很想知道是否存在针对此问题的非迭代解决方案.也许有一种方法可以使用模运算或其他方式来做到这一点……