这段代码的时间复杂度o()是多少? java的

时间:2012-12-28 12:34:58

标签: java performance recursion sum big-o

我认为是O(3 ^ n),有什么想法吗?      此方法查找给定数字是否是给定集合的任何子集合的总和(overoads boolean isSumOf(int [] s,int n))。      如果taget等于0或者消耗集合中的当前数字(或不消耗)并再次尝试,则该方法在每次递归调用中都会查询,      当目标> 0时,我们还没有耗尽阵列。

    * @param set a given set of natural numbers.
    * @param target the number. 
    * @param i where we are in the set.
    * @return true if we reached target, else returns false.
    **/
   private static boolean isSumOf(int[] set,int target,int i)
   {

        // Found the set if we are now at 0.
        boolean isSum = (target==0);
        // Look no further if no more to try.
        if ( target > 0 ) 
        {
            // Look no further if we've exhausted the array.
            if ( i < set.length )
            {
                // Try or consume this number in the set (or not) and try again.
                isSum = isSumOf(set, target - set[i], i)  // Consume the current number in the set and try again recursively. 
                    || isSumOf(set, target - set[i], i+1) // Consume the current number in the set and avdance to rhe next number.
                    || isSumOf(set, target, i+1); // Try the current number and avance to the next number in the set.
            }

        }

        return isSum;

3 个答案:

答案 0 :(得分:3)

你的问题是NP完全的。这些都是坏消息。

好消息是,这是一个众所周知的NP完全问题! Yey!

http://en.wikipedia.org/wiki/Subset_sum

就像在评论中所说的那样,你的算法可以无限期地运行,并且即使是适度的输入大小也会运行很长时间。

如果您对该代码在中等大小的输入中运行有任何希望,您需要重新考虑您的方法。

您的方法中的一个主要问题是您正在计算许多重复的子问题。想想通常的天真Fibonnaci递归实现。

你的子问题,在光明的一面,有一个非常优化的结构,这是一个很好的指标,你的问题将是动态编程方法的一个很好的候选人。它使事情变得更容易,你甚至不需要总和到值的确切数字,只是一个布尔输出。

我链接的维基百科文章讨论了一些伪多项式方法以及通过动态规划的多项式方法。

答案 1 :(得分:1)

它看起来比O(3^n)更糟糕,因为第一个递归调用isSumOf(set, target - set[i], i)会在不推进i的情况下调用自身,对于大型目标,这会导致每个{{1}的大量分支}}

这样的方法可以从Memoization中受益,以降低其复杂性。

答案 2 :(得分:1)

让我们假设该集仅包含数字&gt; 0.另请注意,可以省略第二个递归调用isSumOf(set, target - set[i], i+1)而不更改结果。它相当于首先减去set [i](第一次递归调用)然后推进i(第三次递归调用)。我正在讨论这个简化版本。

如果n是目标而k是集合的大小,我认为复杂度是O(n ^ k)但我没有完整的证明。让我们假设我们列举了所有可能性,并且在我们找到分区时不停止(真正的算法由于快捷方式或||而停止)。最糟糕的情况似乎是集合中的所有元素都是1.所以我们必须提前i k次才能到达递归的末尾,并且对于前进的每一步,我都有少于n种可能性。