时间复杂度之 Master 公式

递归行为时间复杂度的估算:

示例: 求一个数组的最大值 arr[]={3,5,6,2,8,3}

分别求左侧最大值,右侧最大值,最后返回两侧最大值比较后的最大值

int doGetMaxnum(int *arr, int l, int r)
{
	if(l == r)
		return arr[l];
	
	int mid = l + ( (r - l)>>1);
	int leftMax = doGetMaxnum(arr, l, mid);
	int rightMax = doGetMaxnum(arr, mid+1, r);
	
	return fmax(leftMax, rightMax);
}

int getMaxnum(int *arr, int len)
{
	int l = 0;
	int r = len - 1;
	
	return doGetMaxnum(arr, l, r);	
}

 细化一下递归图(其实就是利用系统栈进行多叉树的遍历)

那么对于这类递归行为,怎样去估算其时间复杂度呢?

master 公式可以用来处理这一系列

T(N) = a * T(N / b) + O(N ^ d)

1. log(b, a) > d        -> O(N ^ log(b, a))

2. log(b, a) = d        -> O(N ^ d * logN)

3. log(b, a) < d        -> O(N ^ d)

T(N):母问题的数据量是 N 级别的

T(N/b):每一次的子问题的规模都是 N / b 级别的,等量规模

a:子问题被调用的次数

O(N ^ d):除去子问题调用之外剩下过程的时间复杂度

现在来看示例的时间复杂度:

母问题:

        int doGetMaxnum(int *arr, int l, int r)

        l ~ r 上一共有 N 个数

子问题:

            int leftMax = doGetMaxnum(arr, l, mid);
            int rightMax = doGetMaxnum(arr, mid+1, r);

            规模是  N / 2

a:

        调用了 2 次 等量的子问题

除去子问题外,剩下的内容:

        if(l == r)        // 比较
        int mid = l + ( (r - l)>>1);        // 计算
        fmax(leftMax, rightMax);       // 比较

        所以时间复杂度是 O(1)

那么我们的 master 公式:

        T(N) = 2 * T(N / 2) + O(1)

其中 a = 2, b = 2, d = 0,应用

1. log(b, a) > d        -> O(N ^ log(b, a))

        log(2,2) > 0        -> O(N ^ log(2, 2))        -> O(N^1) -> O(N)

 

再扩展下这个示例的推演:

不进行二分之一分段

1. 左侧 2/3 + 右侧 2/3,即使有重复区域,也不影响计算结果

        子过程的规模是 2/3 * N ,即 T(N / (3/2) )

2. 左侧 1/3 + 中间 1/3 + 右侧 1/3

        子过程的规模 1/3 * N, 即 T(N / 3)

3. 左侧 1/3 + 右侧 2 /3 

        子过程的规模 = T( N /3 ) + T(N / (3/2) )

        不是等量的子过程,不符合 master 公式

4. 左侧 1/3 + 中间 1/3 + 右侧 1/3 完成后,再全部扫描一次数组

        T(N) = 3 * T(N /3) + O(N)

 

一定记住子问题是等量的才行!

更多数据结构算法详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值