繁体   English   中英

非平凡递归函数的时间复杂度

[英]Time complexity of a non-trivial recursive function

我写了一个递归函数,它接受一个正整数(> 0)( denominations )和一个整数值( amount )的数组,并返回仅使用数组中的整数获取值的方式的数量。 因此,例如,整数数组可以被视为变化,整数值被视为您必须支付的金额。 该功能返回您可以支付收银员的方式。 例如:

amount = 4, denominations = [1,2,3,4]

这应该返回5

我测试了我的功能,它工作正常。 调用函数时,参数accindex传递为0.这是函数:

public int count_number_of_ways(int amount, int acc, int index,  int[] denominations) {

        if (acc > amount) return 0;

        if (amount == acc) return 1;


        int len = denominations.length;
        int count = 0;

        while (acc < amount) {


            for (int i = index + 1; i < len; i++) {


                count += count_number_of_ways(amount, acc + denominations[i], i, denominations);


            }

            acc += denominations[index];

            if (acc > amount) return count + 0;

            if (acc == amount) return count + 1;

        }

        return count + 0;


}

我试图计算这个函数的时间复杂度,但碰到了一堵砖墙。 递归调用是在for循环中的for循环内部,这让我感到困惑。 谁能帮我确定这个功能的时间复杂度?

一般来说,在最坏的情况下,您将花费时间与( amount / denominations[0] )*( amount / denominations[1] )* ... *( amount / denominations[n] )成amount ,其中n - 面额数。

这是因为您查看了每种面额的所有计数集。 并且特定面额数i最大计数是amount / denominations[i]

在实际情况下,您会提前停止该过程,但我认为它不会改变O((amount / geometric_average_denomination)^ n)。

但是可以避免指数时间。 为此,您可以使用动态编程方法。 这是我的算法版本需要O(金额* n)时间:

public static int count_number_of_ways(int amount, int index, Integer[][] cache, int[] denominations) {
    if (cache == null)
        cache = new Integer[denominations.length][amount + 1];
    if (amount == 0) {
        int ret = 1;
        cache[index][amount] = ret;
        return ret;
    }
    if (cache[index][amount] != null) {
        return cache[index][amount];
    }
    int ret = 0;
    if (index + 1 < denominations.length)
        ret += count_number_of_ways(amount, index + 1, cache, denominations);
    if (amount >= denominations[index])
        ret += count_number_of_ways(amount - denominations[index], index, cache, denominations);
    cache[index][amount] = ret;
    return ret;
}

该想法是填充大小[n] [金额]的矩阵,其中每个元素(i,j)是使用具有索引> = i的面额子集的金额= j的解的数量。 您只需填充此cache矩阵的每个元素一次,如果已经定义,则稍后重复使用它。

使用它像:

int ret = count_number_of_ways(amount, 0, null, denominations)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM