找到元素小于 S 的子集
find subset with elements smaller than S
我必须找到解决以下问题的算法:
输入是两个自然数 S 和 k 以及一组未排序的 n 对不同数。
在 O(n) 中确定是否存在总计 <=S 的 k 个数字的子集。注意:k不应该是时间复杂度的一部分。
algorithm({x_1, ..., x_n}, k, S):
if exists |{x_i, ..., x_j}| = k and x_i + ... x_j <= S return true
我找不到时间复杂度为 O(n) 的解决方案。
我能得到的是 O(kn),因为我们搜索最小值的 k 倍,总和为:
algorithm(a={x_1, ..., x_n}, k, S):
sum = 0
for i=1,...,k:
min = a.popFirst()
for i=2,...,len(a):
if(a[i] < min):
t = a[i]
a[i] = min
min = t
sum += min
if sum <= S:
return true
else:
return false
这是复杂度为 O(n) 且 return 正确的结果。我怎样才能松开k?
谢谢你的帮助,我真的很纠结这个!
您可以从该集合构建一个大小为 k
的最小堆。构建这个的时间复杂度是 O(n)
预期时间和 O(n log k)
最坏情况。
堆应包含集合中的前 k
个最少元素。
那么直接可以看出堆中元素的总和为<= S
。您不需要从堆中移除元素来计算总和。只需遍历堆计算总和即可。删除所有元素需要 k log k
复杂性。
你甚至不需要考虑下一个更高的元素,因为添加它们会导致总和大于 S
Quickselect 可用于查找 k 个最小元素:https://en.wikipedia.org/wiki/Quickselect
它基本上是快速排序,除了你只在主元有趣的一侧递归。
一个简单的实现在 O(N) 预期 时间内运行,但使用中位数中位数 select一个枢轴,你可以使它成为一个真正的最坏情况界限:https://en.wikipedia.org/wiki/Median_of_medians
我必须找到解决以下问题的算法:
输入是两个自然数 S 和 k 以及一组未排序的 n 对不同数。
在 O(n) 中确定是否存在总计 <=S 的 k 个数字的子集。注意:k不应该是时间复杂度的一部分。
algorithm({x_1, ..., x_n}, k, S):
if exists |{x_i, ..., x_j}| = k and x_i + ... x_j <= S return true
我找不到时间复杂度为 O(n) 的解决方案。
我能得到的是 O(kn),因为我们搜索最小值的 k 倍,总和为:
algorithm(a={x_1, ..., x_n}, k, S):
sum = 0
for i=1,...,k:
min = a.popFirst()
for i=2,...,len(a):
if(a[i] < min):
t = a[i]
a[i] = min
min = t
sum += min
if sum <= S:
return true
else:
return false
这是复杂度为 O(n) 且 return 正确的结果。我怎样才能松开k?
谢谢你的帮助,我真的很纠结这个!
您可以从该集合构建一个大小为 k
的最小堆。构建这个的时间复杂度是 O(n)
预期时间和 O(n log k)
最坏情况。
堆应包含集合中的前 k
个最少元素。
那么直接可以看出堆中元素的总和为<= S
。您不需要从堆中移除元素来计算总和。只需遍历堆计算总和即可。删除所有元素需要 k log k
复杂性。
你甚至不需要考虑下一个更高的元素,因为添加它们会导致总和大于 S
Quickselect 可用于查找 k 个最小元素:https://en.wikipedia.org/wiki/Quickselect
它基本上是快速排序,除了你只在主元有趣的一侧递归。
一个简单的实现在 O(N) 预期 时间内运行,但使用中位数中位数 select一个枢轴,你可以使它成为一个真正的最坏情况界限:https://en.wikipedia.org/wiki/Median_of_medians