對數最常出現的規律可概括爲下列一般法則:
如果一個算法用常熟時間(O(1))將問題的大小削減爲其一部分(通常是1/2),那麼該算法就是O(logN)。另一方面,如果使用常數時間只是把問題減少一個常數的數量(如將問題減少1),那麼這種算法就是O(N)的。
例1:折半查找(二分法)
條件: 給定一個整數X和整數A0,A1,...,A(N-1),後者已經預先排序並在內存中,求下標i使得Ai=X,如果X不在數據中,則返回i=-1。
思路:驗證X是否是居中的元素。如果是,則答案就找到了。如果X小於居中元素,那麼我們可以應用同樣的策略於居中元素左邊已排列的子序列;同理,如果X大於居中元素,那麼我們檢查數據的右半部分。
public static <AnyType extends Comparable<? super AnyType>> int binarySearch(AnyType a[],AnyType x){
int low=0,high=a.length-1;
while(low<=high){
int mid=(low+high)/2;
if(a[mid].compareTo(x)<0)
low=mid+1;
else if(a[mid].compareTo(x)>0)
high=mid-1;
else
return mid;//found
}
return NOT_FOUND;//NOT_FOUND is defined as -1
}
例2:歐幾里得算法-計算最大公因數
兩個整數的最大公因數(gcd)是同事整除兩者的最大整數思路:假設M>=N(否則交換),算法連續計算餘數爲0爲止,最後的非零餘數就是最大公因數。(兩個數的餘數肯定比兩個數的較小那個還要小,所以每次求餘至少縮減一半。)
public static long gcd( long m,long n){
while(n!=0){
long rem = m % n;
m = n;
n = rem;
}
return m;
}
例三:冪運算
計算X^N(N-1次X自乘)
思路:N<=1是這種遞歸的基準情形。否則,若N是偶數,我們有X^N=X^(N/2) * X^(N/2),如果是偶數,我們有X^N=X^((N-1)/2) * X^((N-1)/2) * X。
例如,爲了計算X^62,算法將如下運行,他只用到9次乘法。
X^3=(X^2)*X,
X^7=(X^3)^2 * X,
X^15=(X^7)^2 * X,
X^31=(X^15)^2 * X,
X^62=(X^31)^2
public static long pow( long x ,int n){
if(n==0) return 1;
if(n==1) return x;
if(isEven(n)) return pow(x*x,n/2);//偶數
else return pow(x*x,n/2)*x;
}