大小为k的数组(大小为n)的子集数量,最大和最小元素之间的差异最大为x

时间:2016-11-19 06:48:29

标签: c++ arrays algorithm

我在测试期间遇到了这个问题。给定大小为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)。我没有被卡住,但我的解决方案无法通过测试用例。

2 个答案:

答案 0 :(得分:2)

我认为你走在正确的轨道上。据我所知,这是你到目前为止所拥有的:

  • 对数组进行排序。
    • 你没有说你是怎么做的,但你可以使用基数排序在O( n )时间内完成,所以我假设O( n < / em>)时间。
  • 对于每个元素:
    • 计算 E - x E 之间的其他元素数量(其中 E 是值这个元素)。调用结果 m
      • 你在最糟糕的情况下使用线性搜索在O( n )时间内这样做。
    • 计算 m C k -1
      • 你没有说你是怎么做的,但你可以在O( n )时间内为所有可能的 m 预先计算这个,然后只使用一个常数 - 时间查找,所以我会假设你正在做的事情。

这种方法给出了正确的结果,并且需要最坏情况的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)

我希望它会对你有所帮助。

  1. 首先以递归方式获取长度为k的子集。
  2. 如果当前长度等于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);
    
      }
    
    }