给定两个数字数组a 1 ,a 2 ,a 3 ,…a n和b 1 ,b 2 ,.. b n ,其中每个数字为0或1,这是找到最大跨度(i,j)的最快算法,例如那a i + a i + 1 ,….a j = b i + b i + 1 ,.. b j 。或报告没有这样的跨度,
(A)如果允许散列,则花费O(n 3 )和Ω(2 n)时间
(B)在关键比较模型中花费O(n 3 )和Ω(n 2.5)时间
(C)取θ(n)的时间和空间
(D)仅当2n个元素的和为偶数时才花费O(√n)时间答案: (C)
说明:该问题可以用θ(n)的时间和空间来解决。
这个想法是基于以下观察。
- 由于总共有n个元素,因此两个数组的最大和为n。
- 两个和之间的差从-n到n 。因此,总共有2n +1个可能的差值。
- 如果两个数组的前缀和之间的差在两个点处相同,则这两个点之间的子数组具有相同的和。
以下是完整算法。
- 创建大小为2n + 1的辅助数组,以存储所有可能的差值的起点(请注意,差的可能值从-n到n不等,即,总共有2n + 1个可能值)
- 将所有差异的起始点初始化为-1。
- 将maxLen初始化为0,并将两个数组的前缀和都初始化为0,preSum1 = 0, preSum2 = 0
- 从i = 0到n-1遍历两个数组。
- 更新前缀总和:preSum1 + = arr1 [i],preSum2 + = arr2 [i]
- 计算当前前缀总和的差: curr_diff = preSum1 – preSum2
- 在差异数组中查找索引: diffIndex = n + curr_diff // curr_diff可以为负,并且可以一直到-n
- 如果curr_diff为0,则到目前为止i + 1为maxLen
- 否则,如果第一次看到curr_diff,即当前diff的起始点为-1,则将起始点更新为i
- 否则(第一次未看到curr_diff),然后将i视为终点并找到当前相同总和跨度的长度。如果此长度更大,则更新maxLen
- 返回maxLen
有关完整的运行代码,请参见两个二进制数组中具有相同总和的最长跨度
这个问题的测验