divide and conquer

本文探讨了递归式在算法复杂度分析中的应用,通过mergesort、binarysearch等实例展示了如何利用递归式评估算法效率,并介绍了几种优化递归算法的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刚刚被老妈拉出去健身,所以更的晚了一些。。。


今天这部分是只有视频里面有书上没有的

首先回忆一下上个话题,我们为什么要讲递归式,原因就是分治法中要用到递归式来获得其复杂度。从而评判算法的好坏。

对于一个递归式: T(n) = aT(n/b)+Theta(1)

a表示子问题的个数,n/b表示子问题的大小,Theta(1)表示合并子问题的时候的开销

这里需要注意一点,子问题不能是有重复的情况,比如说算斐波那契数列,用分治法是指数级别的开销(Theta(phi^n),其中phi为黄金分割数),用自底向上的递推则只有Theta(n)的开销。说到斐波那契数列,其实有小于O(n)的算法,一会儿总结里会提到。


接下来写个总结吧:

merge sort

basic idea是先把一个数组分成两半,分别进行merge sort(复杂度是2*O(n/2)),然后把已经merge好的两个数组merge了(复杂度是Theta(n)).

写出递归式是T(n) = 2T(n/2)+Theta(n)

显然,这里我们的两个T(n/2)虽然看上去一样,但并非重复计算,而是分别对两半进行merge,故而不存在冗余计算的情况.

这个大家应该非常熟悉,master method 告诉我们复杂度是nlogn

binary search

这个大家肯定都写过,也能脱口而出它的复杂度是logn

但是既然我们是钻研算法的人,肯定不能满足于此吧。

我先给出它的递归式:T(n) = T(n/2)+Theta(1)

T(n)是指对n个数进行二分查找的复杂度, T(n/2)是指对n/2个数进行二分查找的复杂度,Theta(1)是比较要查找的数和数组中的第n/2个数的运算复杂度

同理,master method 告诉我们上面的递归式的复杂度是logn。

powering a number

这也是很经典的问题,简单的说就是假设计算机不会算乘方,你写一个函数计算x^n。

一个最简单明了的想法就是这样写

int f(float x, int n){
    if (n != 1) return x*f(x,n-1);
    return x;
}
但是稍微想想就会发现我们这里有很多重复计算的地方。比如说,你算x^4,其实只需要x^2再算平方就可以了,并不需要x^3。

这个算法的复杂度是多少呢?O(n),虽然不算大,但我们有更好的。

正如我刚刚所说,算x^n只需要算x^(n/2)或者算x^(n-1)/2就可以了,这取决于n的奇偶性。

我给出它的计算式:

x^n = x^(n/2)*x^(n/2) if n is even

x^n = (x^(n-1)/2)*(x^(n-1)/2)*x if n is odd

再给出它的递归式(这里我们并不在意它的取整情况):

T(n) = T(n/2)+Theta(1)

它的复杂度是logn

给出代码

int f(float x, int n){
    if(n == 1) return x;
    if(n%2 == 0) {
        int temp = f(x,n/2);
        return temp*temp;
    }
    else {
        int temp = f(x,(n-1)/2);
        return temp*temp*x;
    }
}

斐波那契数列

类似于上面的问题,简单的做法是递归的计算

f(n) = f(n-1) + f(n-2)

如果你愿意画一下递归树会发现里面重复计算的子树太多了,简直一直都在重复计算。

        事实上这个复杂度是指数级别的,高达O(phi^n),其中phi = (sqrt(5)-1) / 2

但如果我们顺序递推f(n),每次要计算f(n)时f(n-1)和f(n-2)都已经计算好了。这个计算复杂度是O(n)。

事实上有更牛X的方法,但是一般人估计想不到了。斐波那契数其实有个性质,就是round(phi^n/sqrt(5))就是f(n)。这样可以用我们刚才说的计算数的power的方法计算f(n),复杂度是logn。是不是很厉害呢?

不幸的是由于种种原因,这种算法并不能真正在计算机上实现,因为现在的计算机都是浮点型的计算机,根号5和phi其实都是被一些固定位数的浮点数来表示,在计算过程中会失去一些位,结果就是取整的时候得不到正确的答案。

最后教授介绍了一种复杂度为log(n)且可行的方法。((F(n+1), F(n)) (F(n), F(n-1))) = ((1,1) (1,0))^n,这是一个用矩阵来计算的方法,我给出自己写的实例代码。

可以用一维矩阵替代二维

#include <stdio.h>
int a[2][2] = {{1,1},{1,0}};
int* matrix_multi(int *A, int *B){
	int i, j, k;
	int *temp = new int[4];
	for(i = 0; i < 2; i ++){
		for (j = 0; j < 2; j++){	
		    *(temp+2*i+j) = 0;    
			for (k = 0; k < 2; k ++){	
                                *(temp+2*i+j) = *(temp+2*i+j) + (*(A+2*i+k)) * (*(B+2*k+j));
			}
		}
	}
	return temp; 
}
int* f(int n){
	if(n < 1) return NULL;
	if(n == 1) return *a;
	if(n%2 == 0){
        	return matrix_multi(f(n/2), f(n/2));
    	}
    	else {
        	return matrix_multi(matrix_multi(f((n-1)/2), f((n-1)/2)), *a);
    	}
}
int main(){
	printf("%d", *(f(10)+1));
	return 0;
}

也可直接用二维矩阵

#include <stdio.h> 
int ** matrix_multi(int** A, int** B){
    int ** p = new int *[2];
    for (int i =0; i<2; i++){
        p[i] = new int[2];
    }
    for (int i =0; i<2; i++){
        for(int j = 0; j < 2; j++){
            for (int k = 0; k < 2; k++){
                p[i][j] = p[i][j] + A[i][k]*B[k][j];
            }
        }
    }
    return p;
}
int** f(int** a, int n){  
    if(n < 1) return NULL;  
    if(n == 1) return a;  
    if(n%2 == 0){  
        return matrix_multi(f(a, n/2), f(a, n/2));  
    }  
    else {  
        return matrix_multi(matrix_multi(f(a, (n-1)/2), f(a, (n-1)/2)), a);  
    }  
}  
int main(){ 
    int ** a = new int *[2];
    for (int i =0; i<2; i++){
        a[i] = new int[2];
    }
    a[0][0] = 1;
    a[0][1] = 1;
    a[1][0] = 1;
    a[1][1] = 0;
    printf("%d", *(*f(a, 10)+1));  
    printf("\n");
    return 0;  
}  

上面计算出来的结果都是55,即fibo(10)的结果


计算矩阵的乘法

一般而言矩阵的乘法需要三层for循环,这是一个n^3的算法。strassen提出了一个n^(log2(7))的算法,教授也讲了,这个我就不说了。


VLSI (超大规模集成电路)的布局

其实就是求完全二叉树怎么放占的矩形面积最小,要求每个树的顶点在点阵的点上。

最后面积是O(n),长宽各sqrt(n),做一个H布局。

这个我觉得纯属智力题,老师也没说怎么推导出来的。






 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值