我得到了一个整数数组A.现在我必须找到一个子数组(原始数组的子序列),其中每对的总和大于或等于预定义的K.
我的想法: -
sorted[i] + sorted[i+1]>=k
sorted[i]
对数组的所有元素重复上述步骤。
运行时间: - O(nlgn)
解决方案是否最佳?我们可以进一步改进吗?
示例: -
-10 -100 5 2 4 7 10 23 81 5 25
排序数组
-100 -10 2 4 5 5 7 10 23 25 81
让K = 20
子阵列: -
10 23 25 81
如果问题是找出最长的子阵列,那么alestanis在答案中建议的算法会很好用:)
答案 0 :(得分:3)
这是一个稍微不同的方法,由早期的一条评论暗示,类似于alestanis的答案,但略有不同,因为它不依赖于拆分数组。它只通过数组(尽管不能保证O(N)),只需要跟踪两个最小值以及正在考虑的子序列的起点和终点。
对于连续子序列,使所有可能的对总和为20,两个最小元素的总和必须> = 20.因此,首先考虑后续元素对(array[0]
和array[1]
开始)。如果它们不总和为20或更多,则转到array[1]
和array[2]
。如果它们总计达20或更多,则将右侧端点扩展一个。如果新元素大于其他两个元素,那么对于已经在子序列中的任何内容,它将总和为20或更大,并且您可以再次展开右手。如果它更少,那么你需要通过几个比较选择两个最少的元素,如果两个新的最小元素现在不总和为20或更多,那么从子序列中删除刚刚添加的元素,并注意这个特殊的子序列,然后从现有子序列的第二和第三个元素开始。最后,您通常会得到一个符合约束条件的子序列列表,并且应该很容易选择第一个或最大的或者您需要的任何内容。
示例,使用您列出的序列:
-10 -100 5 2 4 7 10 23 81 5 25
从-10, -100
开始。它们不总和为20,所以向右移动-100, 5
。再次,这些不等于20,所以继续。总和为20的第一对是10, 23
。现在,我们将范围扩展到10, 23, 81
。 81大于两个最小值,因此我们再次扩展到10, 23, 81, 5
。 5小于10和23,所以新的最小值是5和10,不等于20,所以加5是一个错误,我们需要回溯。我们发现10, 23, 81
就是这样一个子序列。接下来我们继续23, 81
,这将引导我们进入符合条件的子序列23, 81, 5, 25
。
因此,最后,我们有四个可能符合标准的子序列 - 10, 23, 81
,23, 81, 5, 25
,81, 5, 25
和5, 25
。一旦我们有一个包含原始列表中最后一个元素的解决方案,最后两个可以通过不找到其他解决方案来修剪,这将只留下前两个可能性。从那里我们可以选择第一个或最长的。
答案 1 :(得分:3)
这是一个相当简单的解决方案。
>>> def f(A, k):
... solution = [item for item in A if 2*item >= k]
... m = min(solution)
... for item in A:
... if item + m >= k and 2*item < k:
... solution.append(item)
... break
... return solution
...
>>> f([-10, -100, 5, 2, 4, 7, 10, 23, 81, 5, 25], 20)
[10, 23, 81, 25]
>>>
答案 2 :(得分:2)
首先,您无法对您的设置进行排序。我认为问题的一部分是找到作为输入给出的原始数组的子数组。
这可以使用一些递归来解决:
m1
和m2
m1 + m2 < K
,则将您的数组拆分为最多两个同时不包含m1
和m2
的较小数组。如果m1
和m2
的索引为i
,j
的索引为i<j
,则子阵列为[O, j-1]
和[i+1, n]
。
从步骤1开始重复。m1 + m2 >= K
那么您当前的数组是解决问题的可行方法:返回其长度。让我们在你的例子中应用这个:
Initialize max = 0;
A1 = -10* -100* 5 2 4 7 10 23 81 5 25
它的两个最小值是-10和-100。围绕这些值拆分数组,这只给我们一个数组(我们很幸运!)
A2 = 5 2* 4* 7 10 23 81 5 25
A2
的两个最小值是2和4.我们分成
A3_1 = 5* 4* and A3_2 = 2* 7 10 23 81 5* 25
这将继续以下迭代:
A3_1 discarded
A3_2 becomes A4_1 = 2* 7* 10 23 81 A4_2 = 7* 10 23 81 5* 25
A5_1 = 7* 10* 23 81
A5_2 = 7* 10* 23 81 -> Duplicate, discarded
A5_3 = 10* 23 81 5* 25
A6_1 = 10* 23* 81 -> Yay! update max = 3
A6_2 = 10* 23* 81 -> Length <= max. Discarded
A6_3 = 23 81 5* 25 -> Yay! update max = 4
在这个例子中,我通过以下方式修剪了搜索空间:
此算法的复杂性为:
答案 3 :(得分:0)
void sub_array(int ar[],int n,int val)
{
int max=0;
for(int i=0;i<n;i++)
{
if(ar[max]<ar[i])
max=i;
}
int b[n];
max=ar[max];
int p=0;
int min=0;
for(int i=0;i<n;i++)
{
if(ar[i]+max>val)
{
b[p]=ar[i];
if(ar[i]<max)
{
min=p;
max=ar[i];
}
p++;
}
else
{
if(ar[i]>max)
{
max=ar[i];
b[min]=ar[i];
}
}
}
for(int i=0;i<p;i++)
{
cout<<b[i]<< " " ;
}
}