我在测试期间遇到了这个问题。给定大小为n的数组,找到大小为k的子集的数量,其中最大和最小元素之间的差异最多为x。
Constraints 1<=a[i],n,k,x<=10^6
Example:n=5 k=3 x=5 a={1,2,3,4,5}
output: 10
我的方法到目前为止: 我首先对数组进行了排序并考虑了最大的元素。现在使用线性搜索我找到了最小元素,其差异小于或等于x。
现在如果我拿出那个最大的元素并在它们之间选择任何k-1元素。选择过程是(最大的索引 - 最小的索引)C(k-1),我总结了这些。
复杂性即将来临(nnk)。我没有被卡住,但我的解决方案无法通过测试用例。
答案 0 :(得分:2)
我认为你走在正确的轨道上。据我所知,这是你到目前为止所拥有的:
这种方法给出了正确的结果,并且需要最坏情况的O( n 2 )时间。 (你提到你得到了O( n 2 k )时间;但我没有看到任何理由。)
您似乎缺少的主要优化是,您可以从上一个元素的线性搜索停止的位置恢复线性搜索,而不是重新启动每个元素的线性搜索。这样,所有线性搜索放在一起将加起来为线性时间,因为它们只相当于一次通过数组。 (换句话说,您的线性搜索将具有摊销的常量时间。)
这为我们提供了一个O( n )时间的算法:
sort a
precompute nCr(m, k - 1) for all m in (0 .. n-1)
set total_num_subsets := 0
set min_element_index := 0
for max_element_index in 0 .. n-1 do:
while a[min_element_index] + x < a[max_element_index] do:
set min_element_index := min_element_index + 1
set num_eligible_elements := max_element_index - min_element_index
set num_subsets := nCr(num_eligible_elements, k - 1)
set total_num_subsets := total_num_subsets + num_subsets
(我们可以做一些额外的小优化 - 例如,我们可以在max_element_index
而不是k
开始0
次迭代,我们可以使用memoization而不是precomputation来避免计算 m C k -1 以获得更大的 m值比实际上最终需要的 - 但它们不会改变算法的复杂性。)
答案 1 :(得分:0)
我希望它会对你有所帮助。
如果当前长度等于k
2.1然后存储在辅助数组 a 中,长度为k
2.2将其分类为k * log(k)
2.3获得第一个和最后一个元素之间的绝对差异。(首先是最小值,最后一个是最大值)
2.4检查差异小于等于4然后计数++;
public class AllSubSetOfSizeK
{
static int count=0;
public void get_SubSet(int[] A, int k, int start_index, int curr_Len, boolean[] used)
{
int a[]=new int[k];
int l=0;
if (curr_Len == k) {
for (int i = 0; i < A.length; i++) {
if (used[i] == true) {
a[l++]=A[i];
}
}
Arrays.sort(a);//To Sort the Array of k length
if(Math.abs(a[0]-a[k-1])<=4);
count++;
return;
}
if (start_index == A.length) {
return;
}
used[start_index] = true;
get_SubSet(A, k, start_index + 1, curr_Len + 1, used);
used[start_index] = false;
get_SubSet(A, k, start_index + 1, curr_Len, used);
}
public static void main(String[] args)
{
int A[] = { 1,2,3,4,5};
boolean[] B = new boolean[A.length];
AllSubSetOfSizeK obj = new AllSubSetOfSizeK();
obj.get_SubSet(A, 3, 0, 0, B);
System.out.println(count);
}
}