使用二进制搜索找到最大子数组

时间:2019-06-29 01:37:48

标签: arrays algorithm binary-search sub-array

您有两个数组arr1和arr2,要查找子数组的最大大小,该子数组同时是arr1和arr2的子数组

例如:

arr1 = [3,2,1, 4,5]
arr2 = [1,2,3,4,3,2,1]
return is 3 ([3,2,1])

此问题有一个二进制搜索解决方案,可为您提供

O(nlogn) 

复杂性。

有人知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

因此,我将提供一个总体思路。如果句子结构不清楚,有人编辑答案

好的,那么我们怎么知道二进制搜索在这里适用,假设让我们将mid =(l +(r-l)/ 2)作为最长的公共子数组的长度。 现在,如果我们有一个长度为L的公共子数组,那么必须有一个长度小于L的公共子数组,如果两个数组没有长度为L的公共子数组,那么它们就不能有任何长度大于L的公共子数组。 L.因此,现在执行二进制搜索的方法应该很简单,即检查是否存在中间长度(可能存在的长度) 一个大小为mid的公共子数组,如果是,则存在可能存在更大长度的公共子数组的可能性,因此我们将当前满足的长度存储为答案,并使l = mid + 1,以检查是否有更大的可能更大的长度,以及是否存在某个更大的长度二进制搜索的迭代过程,我们发现不存在长度为mid的公共子数组,没有增加长度的含义,因此我们选择了r = mid-1的较短长度。 用C ++编写代码

  int l = 1 , r = min(array1.size() , array2.size()); // taking min length of array 1 and array2
  int answer = -1;
  while(l <= r)
  {
      int mid = ( l + ( r - l) / 2);
      if(check(array1 , array2 , mid))
      {
          answer = mid;
          l = mid + 1;
     }
     else
       r = mid - 1;
 }
 cout << answer << "\n";

现在问题来了,我们如何检查给定长度L和两个数组,如果在给定长度L的两个数组中都存在一个公共子数组,那么您必须了解实际上试图给出的散列一个数组的唯一数值,这样就容易比较两个不同的数组,即两个相同的数组具有相同的哈希值,而不同的数组具有不同的哈希。因此存在不同的哈希方法,但是您可能已经猜到了,这可能是两个不同的数组具有相同哈希值的情况,这称为碰撞,因此,如何减少它,我们可以通过使用一种强哈希方法来减少它,即碰撞的可能性。这些方法之一是滚动哈希,有关更一般的想法,请查看有关Internet上滚动哈希的信息。

现在在二进制搜索中的每次检查中,计算长度为mid的所有子数组的滚动哈希并将其存储在像哈希表或集合这样的数据结构中。然后再次计算第二个数组中所有长度为中间的子数组的滚动哈希,但是这一次在计算时,仅检查此哈希值是否已经计算并存储在您的datastructre中,用于第一个数组的子数组,在hashtable中(平均查找时间为O(1))或集合(平均查找时间为对数),如果是,则存在此中等长度的公共子数组,并且对二进制搜索返回true,但是在每次检查第二个数组中的长度窗口之后,您不会如果找不到任何已经存在的哈希,则返回false。 因此,假设您将哈希表作为数据结构,则总时间复杂度将为

(array1.size()+ array2.size())* log(min(array1.size(),array2.size()))

因为您在二进制搜索中迭代log(min(array1.size(),array2.size())次,并且在每次迭代中,都通过遍历检查两个数组,计算滚动哈希并检查哈希表,即(array1 .size()+ array2.size())。