一、給定 個大整數 和 ,它們分別有 位和 位數字,且 。 當 比 小很多時,設計一個算法用 時間求出 的值。說明分析思路,寫出僞代碼,並寫出算法複雜度分析過程。
解:
考慮到比小很多,可以把m位乘n位的問題拆解爲多個m位相乘的問題,然後利用已經得出的m位相乘的優化算法進行計算。
將 分解爲 段,使得每段爲位,那麼類似大整數乘法的計算方法,這裏計算就相當於計算次位的乘法運算,然後在進行次加法。利用已經知道的分治法求位乘積複雜度爲,所以求的時間複雜度爲.
僞代碼:
/**
*計算位數爲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;
}
二、 設 個不同的整數(可能爲正整數、負整數或者0)排序後存於數組 中。 設計一個算法,判斷數組中是否存在不動點(若元素 等於 , 即 ,則此元素爲不動點)。說明分析思路,寫出僞代碼,並寫出算法複雜度分析過程。
解:
因爲每個數都是整數,並且數組是升序的,假設其中某個位置的A[i] = i,那麼可以肯定的值,之前的A[x] > x,之後的A[x] < x,那麼這個問題除了判斷相等的條件不同,其他和課上講的二分搜索幾乎一樣,所以可以和二分搜索一樣使用分治法和遞歸進行計算。
因爲每次都是執行二分操作,每次遞歸中間的操作複雜度都爲,所以,總的複雜度的遞歸表達式爲
由主方法得時間複雜度爲:
僞代碼:
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;
}