该算法的比特成本时间复杂度是多少(Java 示例)?

Posted

技术标签:

【中文标题】该算法的比特成本时间复杂度是多少(Java 示例)?【英文标题】:What is the bit cost time complexity of this algorithm (Java example)? 【发布时间】:2021-01-10 19:59:04 【问题描述】:

我编写了以下 Java 代码,用于使用分而治之的方法计算在位向量中找到的 1:s 的数量。我试图找出算法“count”的时间复杂度,假设我们有一个函数IsZero(int []arr, int low, int high)(可能不切实际)在 O(1) 中运行,如果 low之间的所有位都返回 true > 和 high 为 0。我将包含一个主要方法来解释如何使用该算法,以及我自己的 IsZero 实现(它不会以 O(1) 复杂度运行)。所以,问题是。考虑到 IsZero 的复杂度为 O(1),这个算法的时间复杂度是多少?

Class Algorithm 

   static int NumberOfOnes(int v[]) 
       return count(v, 0, v.length-1);
   

   static boolean IsZero(int arr[], int low, int high)
     for(int i = low; i <= high; i++)
         if(arr[i] == 1)
            return false;
         
     
     return true;
   

   static int count(int arr[], int low, int high)

         if (low == high && arr[low] == 1) 
             return 1;
         
         
         if (high - low == 1) 
             return arr[low] + arr[high];
         

         if(IsZero(arr, low, high)) 
             return 0;
         

         int mid = (low + high) / 2;
         return count(arr, low, mid) + count(arr, mid + 1, high);
   

   public static void main(String args[]) 
       int arr[] = 1,1,0,0,0,0,1,0,1,1;
       int k = NumberOfOnes(arr);
       System.out.println(k); //Should print 5 as result
   




【问题讨论】:

IsZero(...) 怎么可能是 O(1)? @AndyTurner 如果 IsZero 可能为 O(1),那么找出总复杂性是多少是任务的一部分,但我似乎无法弄清楚复杂性,即使我开发了一种可以解决问题的工作算法。如果有人对同一问题有不同的解决方案,并且他们知道解决方案的复杂性,我也很乐意看看。 大 O 是最坏情况下的复杂性,所以如果 isZero 是 O(1),你总是假设它永远不会通过,你必须做更多的工作 -> 整个问题归结为分而治之的访问全部,O(n.log(n))。如果 isZero 不是 O(1) 而是 O(f(n)),则只需将整个乘以它并 reduce = O(n.log(n).f(n))。 查看您的计数方法 - 在最坏的情况下(全为 1),它每次都将搜索空间除以 2,直到达到低 = 高(一位数)。您应该认识到这与二叉树搜索所需的过程相同,因此您可以计算出复杂性:***.com/a/13093274/223806 @VojtěchKaiser 这不是 O(n log n),您只是在搜索一个列表。 【参考方案1】:

复杂度为 O(1+k*log(n))

与分而治之的算法一样,您可以通过将问题一分为二并分别解决这两个部分来解决更大的问题。这为您提供log(n)“层”,其中每个后续层的子问题是前一层的两倍。但是,我们可以直接丢弃一些层(如果它们没有层),这意味着在任何时候我们最多处理 k 个子问题。对于每个子问题,我们调用一次 IsZero,因此我们最多做 k 个“事情”,总共 log(n) 次,这导致 O(1+k*log(n))。请注意,如果 k=0,则添加 1。

但更严格的界限是 O(1 + min(n, k*log(n)))

与其他常见的 D&C 算法(例如 MergeSort)不同,您实际上在每一层都没有线性步长。这意味着在最坏的情况下(不能丢弃任何子问题),您在第一层最多做 1 个“事情”,在第二层最多做 2 个“事情”,然后是 4、8、16 等等,直到你做 n最后一层的“东西”。这个总和等于2n-1,当然是O(n)

因此O(n)O(1+k*log(n)) 都是正确的,因此更严格的界限是O(1 + min(n, k*log(n)))

当然,您可以在 O(n) 中执行此操作并不令人惊讶,因为简单的解决方案在 O(n) 中,但我发现它是您算法的一个相当简洁的属性。

【讨论】:

@VojtěchKaiser 所描述的算法在 O(1 + min(n, k*log(n))) 中。它不需要k的先验知识来实现​​这一点。 min(f1, f2) 并不是因为算法可以根据 k 的值做出某种决策,而是因为 f1 和 f2 都是渐近上界。

以上是关于该算法的比特成本时间复杂度是多少(Java 示例)?的主要内容,如果未能解决你的问题,请参考以下文章

该算法查找所有组合的时间复杂度是多少?

[动态规划]338. 比特位计数

338. 比特位计数

338. 比特位计数

这个5行Java算法的时间复杂度是多少?

leetcode-338. 比特位计数