题目暂且不说,我们考虑一个简化版的题目。
设有同长度为n的两个比特串(0,1序列),可以任意移动(左或者右)其中一个任意距离的情况下,求出能够重叠的1的数量。
不妨假设a=【1,1,1,0】b=【0,0,1,1】我们初始化一个长度为2倍的全为0的数组【0,0,0,0,0,0,0,0】
然后求a里的每个1与b里的每个1差了有多远,
可以得到a0-b2=-2,a0-b3=-3,a1-b2=-1,a1-b3=-2,a2-b2=0,a2-b3=-1.
负数代表“向右”,也就是说如果a0与b2重合,需要把a右移2单位,之后的以此类推。
因为a1-b3=-2 也就是说右移2单位后,a1与b3也是可以重叠的,那么我们可以用映射表来递增表示右移2单位就能有“2位重合”。
整理上述六个表达式得到{-2:2,-1:2,-3:1,0:1}(不用介意顺序)。分别表示右移|n|个单位能得到的重叠数。
网络上有人给出来的解法是用了二维数组来记录。
实际上python的一个点对(i,j)就可以用作哈希键,因此这个对表示向上i个单位,向右j个单位。
写成代码表示就是:
distance={}
ans=0
for ia in range(len(A)):
for ja in range(len(A)):
if A[ia][ja]==1:
for ib in range(len(B)):
for jb in range(len(B)):
if B[ib][jb]==1:
distance[(ia-ib,ja-jb)]=distance.get((ia-ib,ja-jb),0)+1
ans=max(distance[(ia-ib,ja-jb)],ans)
这里实际上与一维比特序列计算方法完全一致,只是变成了二维双重for循环。
就是对应着:“我移动(i,j)步数这两个1就能重叠,那么如果还有另外的两个1能通过(i,j)步数到达,那重叠就增加1”.
解法很精妙,我们使用哈希表来更直观地求解。