📜  门| GATE-CS-2006 |第 54 题

📅  最后修改于: 2021-09-25 04:53:37             🧑  作者: Mango

给定两个数字数组 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) 的时间和空间内解决。

该想法基于以下观察结果。

  1. 由于总共有 n 个元素,因此两个数组的最大总和为 n。
  2. 两个和之间的差值从-nn不等。所以总共有 2n + 1 个可能的差异值。
  3. 如果两个数组的前缀和之间的差在两点变得相同,则这两个点之间的子数组具有相同的和。

下面是完整的算法。

  1. 创建一个大小为2n+1的辅助数组来存储所有可能的差值的起始点(注意差的可能值从-n到n不等,即总共有2n+1个可能值)
  2. 将所有差异的起点初始化为 -1。
  3. maxLen初始化为 0,两个数组的前缀和为 0, preSum1 = 0, preSum2 = 0
  4. 从 i = 0 到 n-1 遍历两个数组。
    1. 更新前缀和:preSum1 += arr1[i], preSum2 += arr2[i]
    2. 计算当前前缀和的差值: curr_diff = preSum1 – preSum2
    3. 在 diff 数组中查找索引: diffIndex = n + curr_diff // curr_diff 可以是负数并且可以一直到 -n
    4. 如果curr_diff 为 0,则到目前为止 i+1 为 maxLen
    5. Else 如果第一次看到curr_diff,即当前diff的起点为-1,则将起点更新为i
    6. 否则(第一次没有看到 curr_diff),然后将 i 视为终点并找到当前相同总和跨度的长度。如果这个长度更大,则更新 maxLen
  5. 返回最大长度

有关完整的运行代码,请参阅两个二进制数组中具有相同总和的最长跨度
这个问题的测验