划分和征服算法

时间:2017-06-06 05:12:48

标签: algorithm

几周前,我接受了一次面试,并被要求设计一种分治算法。我无法解决问题,但他们只是打电话给我进行第二次采访!这是一个问题:

我们输入两个n元素数组A [0..n - 1]和B [0..n - 1](其中 整数和整数值不一定排序。给出O(nlogn)除法和征服算法,该算法确定是否存在不同的值i,j(即,i!= j),使得A [i] + B [j] =值。如果i,j存在,则算法应返回True,否则返回False。您可以假设A中的元素是不同的,B中的元素是不同的。

任何人都可以解决问题吗?感谢

4 个答案:

答案 0 :(得分:0)

以下算法不使用Divide and Conquer,但它是解决方案之一。 您需要对两个数组进行排序,维护元素的索引可能会排序成对的数组(elem, index)。这需要O(n log n)时间。

然后您可以应用合并算法来检查是否有两个元素,例如A [i] + B [j] = value。这将是O(n)

整体时间复杂度为O(n log n)

答案 1 :(得分:0)

我的方法是......

  1. 排序任何数组。这里我们对数组进行排序A.使用Merge Sort算法对其进行排序,这是一种Divide and Conquer算法。
  2. 然后,对于B的每个元素,按Required Value- Element of B搜索数组A中的Binary Search。这又是一个Divide and Conquer算法。
  3. 如果您从数组A中找到元素Required Value - Element of B,那么Both元素将成对Element of A + Element of B = Required Value
  4. 因此,对于时间复杂性,A包含N个元素,因此Merge SortO(N log N)采用Binary Search而我们会为{B}的每个元素执行O(N log N)元素)需要O(N log N)。总时间复杂度为i != j

    正如您所提到的,如果A[i] + B[j] = value需要检查N * 2,那么您可以在此处获取尺寸为enumerate的2D数组。每个元素与其原始索引配对,作为每行的第二个元素。将根据存储在第一元素中的数据进行排序。然后,当您找到元素时,您可以比较两个元素原始索引并相应地返回值。

答案 2 :(得分:0)

我建议使用哈希。即使不是你应该解决问题的方式,也值得一提,因为散列具有更好的时间复杂度O(n) v。O(n*log(n)),这就是为什么更有效率。

  1. A转换为 hashset (或词典,如果我们想要i索引) - O(n)
  2. 扫描B并检查hashset(字典)中是否有value - B[j] - O(n)
  3. 所以你有一个O(n) + O(n) = O(n)算法(更好需要(O n * log(n)),但解决方法是划分和征服):< / p>

    示例C#实现

      int[] A = new int[] { 7, 9, 5, 3, 47, 89, 1 };
      int[] B = new int[] { 5, 7, 3, 4, 21, 59, 0 };
    
      int value = 106; // 47 + 59 = A[4] + B[5]
    
      // Turn A into a dictionary: key = item's value; value = item's key 
      var dict = A
        .Select((val, index) => new {
          v = val,
          i = index, })
        .ToDictionary(item => item.v, item => item.i);
    
      int i = -1;
      int j = -1;
    
      // Scan B array
      for (int k = 0; k < B.Length; ++k) {
        if (dict.TryGetValue(value - B[k], out i)) {
          // Solution found: {i, j} 
          j = k;
    
          // if you want any solution then break
          break;
    
          // scan further (comment out "break") if you want all pairs
        }
      }
    
      Console.Write(j >= 0 ? $"{i} {j}" : "No solution");
    

答案 3 :(得分:0)

如果没有排序,似乎难以实现。

如果您保持数组未排序,检查是否存在A[i]+B[j] = Value需要时间Ω(n)来修复i,然后检查所有i需要Θ(n²),除非你找到了在B中添加订单的技巧。

平衡分配&amp;对未排序的数组进行征服似乎没有任何好处:如果将AB分成两半,则解决方案可以位于Al/BlAl/Br之一,{ {1}},Ar/Bl这会产生一个重复Ar/Br,它有一个二次解。

如果允许排序,Sanket Makani的解决方案是可能的,但在搜索阶段的时间复杂度方面做得更好。

确实,假设T(n) = 4 T(n/2)A现已排序并考虑2D函数B,它在两个方向A[i]+B[j]i都是单调的。然后,域j受到单调曲线A[i]+B[j] ≤ Value或等效j = f(i)的限制。但是,对于曲线的所有点,必须彻底检查严格相等i = g(j),并且在最坏的情况下无法避免在任何地方评估A[i]+B[j] = Value

f开始,您通过二分法搜索获得i = 0。然后,您可以逐步跟随边界曲线。您将在f(i)方向执行n步骤,并在i方向执行最多n步骤,以便复杂性仍由j限制,是最佳的。

下面是一个示例,显示总和低于和高于目标值的区域(有两个匹配)。

enter image description here

这种最佳解决方案与Divide&amp; amp;征服。也许有可能基于中心点的总和的评估来设计变体,这允许丢弃整个象限,但这将是非常人为的。