我们输入两个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中的元素是不同的。
任何人都可以解决问题吗?感谢
答案 0 :(得分:0)
以下算法不使用Divide and Conquer,但它是解决方案之一。
您需要对两个数组进行排序,维护元素的索引可能会排序成对的数组(elem, index)
。这需要O(n log n)
时间。
然后您可以应用合并算法来检查是否有两个元素,例如A [i] + B [j] = value。这将是O(n)
整体时间复杂度为O(n log n)
答案 1 :(得分:0)
我的方法是......
Merge Sort
算法对其进行排序,这是一种Divide and Conquer
算法。Required Value- Element of B
搜索数组A中的Binary Search
。这又是一个Divide and Conquer
算法。Required Value - Element of B
,那么Both元素将成对Element of A + Element of B = Required Value
。因此,对于时间复杂性,A
包含N
个元素,因此Merge Sort
将O(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))
,这就是为什么更有效率。
A
转换为 hashset (或词典,如果我们想要i
索引) - O(n)
B
并检查hashset(字典)中是否有value - B[j]
- O(n)
所以你有一个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;对未排序的数组进行征服似乎没有任何好处:如果将A
和B
分成两半,则解决方案可以位于Al/Bl
,Al/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
限制,是最佳的。
下面是一个示例,显示总和低于和高于目标值的区域(有两个匹配)。
这种最佳解决方案与Divide&amp; amp;征服。也许有可能基于中心点的总和的评估来设计变体,这允许丢弃整个象限,但这将是非常人为的。