算法题02:递归:大整数乘法的变式、二分搜索

一、给定 22 个大整数 uuvv,它们分别有 mm 位和 nn 位数字,且 mnm\le n。 当 mmnn 小很多时,设计一个算法用 O(nmlog(3/2))O(nm^{\log(3/2)})时间求出 uvuv 的值。说明分析思路,写出伪代码,并写出算法复杂度分析过程。

​ 考虑到mmnn小很多,可以把m位乘n位的问题拆解为多个m位相乘的问题,然后利用已经得出的m位相乘的优化算法进行计算。

​ 将vv 分解为n/mn/m 段,使得每段为mm位,那么类似大整数乘法的计算方法,这里计算uvuv就相当于计算n/mn/mmm位的乘法运算,然后在进行n/m1n/m-1次加法。利用已经知道的分治法求mm位乘积复杂度为O(mlog3)O(m^{log^{3}}),所以求uvuv的时间复杂度为O((n/m)mlog3)+O(n/m)=O(nmlog(3/2))O((n/m)m^{log^{3}}) + O(n/m) = O(nm^{log(3/2)}).

伪代码

/**
 *计算位数为m,n,且m<n的两十进制数乘积,使得时间复杂度为O(nm^log(3/2))
 */

//十进制的同位大整数乘法,且位数为n.
public static int bigMul(int x,int y,int n){
    if(n == 1){
        return x*y;	
    }
    int k = n/2;
    int b = x % pow(10,n/2);
    int a = x / pow(10,n/2);
    int d = y % pow(10,n/2);
    int c = y / pow(10,n/2);
    return bigMul(a,c,k)*pow(2,2*k)+((a-b)*(d-c)+bigMul(a,c,k)+bigMul(b,d,k))*pow(2,k)+bigMul(b,d,k);
}
public static int main(){
    Scenner(int u,int v,int m,int n);	//输入u,v,m,n
    int res=0;							//结果
    int divide_V[n/m]; 		//定义存放将v分为n/m个长为m的数的数组
    //将v划分并存入数组
    for i=0 to i=n/m-1:
    	divide_V[i] = v%pow(10,m);
    	v /= pow(10,m);
    //将数组内的数与m使用上面定义的函数分别相乘,再分别乘以对相应段的位数,如2343->23 43,23参与乘法后还要乘10的2次方,最后全部相加
    for i=0 to i=n/m-1:
    	res += bigMul(u,divide_V[i],m) * i*pow(10,m);//第i段的应该补的位数恰为i*10的m次方
    
    return res;
}

二、 设 nn不同的整数(可能为正整数、负整数或者0)排序后存于数组 T[0:n1]T[0:n-1]中。 设计一个算法,判断数组中是否存在不动点(若元素 T[i]T[i] 等于 ii, 即 T[i]=iT[i]=i,则此元素为不动点)。说明分析思路,写出伪代码,并写出算法复杂度分析过程。

解:

​ 因为每个数都是整数,并且数组是升序的,假设其中某个位置的A[i] = i,那么可以肯定的值,之前的A[x] > x,之后的A[x] < x,那么这个问题除了判断相等的条件不同,其他和课上讲的二分搜索几乎一样,所以可以和二分搜索一样使用分治法和递归进行计算。

​ 因为每次都是执行二分操作,每次递归中间的操作复杂度都为O(1)O(1),所以,总的复杂度的递归表达式为

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

​ 由主方法得时间复杂度为:O(logn)O(logn)

伪代码:

public static int hasPoint(int start, int end,int T[]){
    int mid = (end - start) / 2 + start;
    if(start > end):
        return false;
    
    if(T[mid] == mid):		
    	return true;
    else if(T[mid]<mid):
    	start = mid+1;			//此时值小于下标,应该在右边
    	return hasPoint(start,end,T);
    else if(T(mid)>mid)						//此时值大于下标,那么可能的值就在左边
    	end = mid-1;
        return hasPoint(start,end T);
    return false;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章