给定一个数组,我想找到最大的元素子集,使得子集的最小和最大元素相隔小于或等于K.具体来说,我想要的元素,而不仅仅是大小。如果有多次出现,则可以匹配。
例如,在数组[14,15,17,20,23]
中,如果K为3,则可能的最大子集为[14,15,17]
。如果将17替换为16,则同样如此。此外,应匹配多个元素,例如[14,14,14,15,16,17,17]
。数组不一定是排序的,但它可能是一个很好的起点来排序它。元素不一定是整数,子集在原始数组中不一定是连续的 - 我只想要出现最大可能的子集。
为了更清楚地说明所需的结果,一种天真的方法是首先对数组进行排序,迭代排序数组的每个元素,然后创建一个包含当前元素的新数组,该数组被扩展为包含每个元素之后的所有元素。当前元素< = K大于它。 (即在上面的第一个示例中,如果当前元素为20,则数组将扩展为[20,23]然后因为到达数组的末尾而停止。如果当前元素为15,则数组将被扩展至[15,17]然后停止,因为20大于15大于3.)然后将针对当前最大值检查该阵列,如果它更大,则将替换当前最大值。然后,当前最大值是最大的子集。 (在最大子集是数组的情况下,该方法具有复杂度O(N ^ 2)。)
我知道这种天真的方法,这个问题是要求优化算法。
虽然我可以使用通用算法运行,但Python中的解决方案更可取。
答案 0 :(得分:1)
我认为我们无法通过排序来修改数组&我们必须找出最大的连续子集,所以我的解决方案(在python 3.2中)是:
arr = [14, 15, 17, 20, 23]
k = 3
f_start_index=0
f_end_index =0
length = len(arr)
for i in range(length):
min_value = arr[i]
max_value = arr[i]
start_index = i
end_index = i
for j in range((i+1),length):
if (min_value != arr[j] and max_value != arr[j]) :
if (min_value > arr[j]) :
min_value = arr[j]
elif (max_value < arr[j]) :
max_value = arr[j]
if(max_value-min_value) > k :
break
end_index = j
if (end_index-start_index) > (f_end_index-f_start_index):
f_start_index = start_index
f_end_index = end_index
if(f_end_index-f_start_index>=(length-j+1)): # for optimization
break
for i in range(f_start_index,f_end_index+1):
print(arr[i],end=" ")
这不是最有效的解决方案,但它可以完成您的工作。
经过测试:
1。输入:[14, 15, 17, 20, 23]
1.输出:14 15 17
2,输入:[14,14,14,15,16,17,17]
2.输出:14 14 14 15 16 17 17
3.输入:[23 ,20, 17 , 16 ,14]
3.输出:17 16 14
4.input:[-2,-1,0,1,2,4]
4.输出:-2 -1 0 1
对于输入数字4,有两个可能的答案
但是如果我们必须在数组中找到最大子集,可能连续也可能不连续,那么解决方案会有所不同。
答案 1 :(得分:1)
这看起来非常类似于你的“幼稚”方法,但它的O(n)不包括排序,所以我认为你不能改进你的方法。优化是使用索引,只有在知道答案后才创建第二个数组:
def largest_less_than_k_apart(a, k):
a.sort()
upper_index = lower_index = max_length = max_upper_index = max_lower_index = 0
while upper_index < len(a):
while a[lower_index] < a[upper_index] - k:
lower_index += 1
if upper_index - lower_index + 1 > max_length:
max_length = upper_index - lower_index + 1
max_upper_index, max_lower_index = upper_index, lower_index
upper_index += 1
return a[max_lower_index:max_upper_index + 1]
a = [14,15,17,20,23]
print largest_less_than_k_apart(a, 3);
输出:
[14, 15, 17]
它通过排序数组,当前索引存储在upper_index
中,另一个索引lower_index
尽可能滞后,同时仍指向大于或等于K的值小于当前元素的值。该函数跟踪两个索引尽可能远的距离,并使用这些索引拆分列表并返回子集。
处理重复元素,因为lower_index
尽可能落后(指向最早的副本),而当upper_index
指向最后一个副本时,索引的差异将是最大的给定子集。
传递k的负值是无效的。
答案 2 :(得分:-1)
蛮力方法:
arr = [14,14,14,15,16,17,17]
max_difference = 3
solution = []
for i, start in enumerate(arr):
tmp = []
largest = start
smallest = start
for j, end in enumerate(arr[i:]):
if abs(end - largest) <= max_difference and abs(end - smallest) <= max_difference:
tmp.append(end)
if end > largest:
largest = end
if end < smallest:
smallest = end
else:
break
if len(tmp) > len(solution):
solution = tmp
尝试优化它! (提示:内部循环不需要像在这里那样运行多次)
答案 3 :(得分:-1)
这种低效算法(O(n ^ 2))非常简单:
l = [14,15,17,20,23]
s = max((list(filter(lambda x: start<=x<=start+3, l)) for start in l), key=len)
print(s)
答案 4 :(得分:-1)
快速方法,复杂的O(n * log(n))用于排序,O(n)用于搜索最长的链:
list_1 = [14, 15, 17, 20, 23]
k = 3
list_1.sort()
list_len = len(list_1)
min_idx = -1
max_idx = -1
idx1 = 0
idx2 = 0
while idx2 < list_len-1:
idx2 += 1
while list_1[idx2] - list_1[idx1] > k:
idx1 += 1
if idx2 - idx1 > max_idx - min_idx:
min_idx, max_idx = idx1, idx2
print(list_1[min_idx:max_idx+1])