上周末,我在接受采访时被问到这个问题。有一系列正数。从这个数组中,您需要找出子集。从这个子集中,您应该能够获取任意两个数字,并且它们的总和将始终大于k。 k是用户输入的值。
我能够在两次通过中解决这个问题。在第一遍中,我将拾取大于k的所有项并将它们放在子数组中。在这样做的同时,我将从该子集中找出最小值。
在下一遍中,我将按降序对数组进行排序。之后,我将通过将它们与子集中的最小数字相加来继续向子集添加数字。
上面提到的解决方案解决了这个问题。然而,时间复杂度将是O(n + nlogn)。然而,面试官希望它是O(n)。不用说我无法做到这一点。请帮我解决这个问题。我确实试图搜索互联网。但是我找不到任何具有o(n)时间复杂度的东西。
答案 0 :(得分:3)
k/2
的所有数字添加到子集中(跟踪最小值)。再次浏览数组并将任何大于k-minimum of subset
的数字添加到子集中。我们添加1后停止。
如果这是要求的一部分,您可以寻找最大的要求。
这在O(n)
中运行。
这里的推理如下:
> k/2
的加起来都会超过k
。<= k/2
,则另一个元素需要> k/2
才能加起来至少为k
,因此不能有多个元素{{1 (如果有2个,那么2个加起来不会超过<= k/2
)。此示例为k
,输出为k = 10, array = [3,4,8,9,10]
或[3,8,9,10]
。第一步会添加[4,8,9,10]
,然后我们会在第二步中添加8,9,10
或3
。
技术说明:“子集”表示独特元素。我们可以使用哈希表来获得期望的(但不能保证)4
复杂性。如果它是“子序列”(不是唯一元素),我们可以将它们添加到O(n)
复杂度的数组或链表中。
答案 1 :(得分:0)
是的,可以用复杂度O(n)来解决它。在阵列上使用单个循环时,仅采用大于k / 2的数字。 一个简单的算法如下所示:
for(int i=0; i<n; i++){
if(arr[i] > k/2.0){
add arr[i] to the subset
}
}