N的增长要快于log的任意的幂。对数(logN)最常出现的规律可概括为下列一般法则:如果一个算法用常数时间将问题的大小消减为其一部分(通常为1/2)(例如分治算法),那么该算法就是O(logN)。另一方面,如果使用常数时间只是把问题减少一个常数的数量(如将问题减少1),那么这种算法就是O(N)的。
时间复杂度中的O(logN)的例子
1.折半查找
给定一个整数X和整数A0,A1,···,AN-1,后者是已经预先排序并存在内存中,求下标i使得Ai=X,如果X不在数据中,则返回i=-1。
public static <T extends Comparable<? super T>> int binarySearch(T[] a, T 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; } return -1; }
循环从high-low=N-1开始并在high-low<=-1结束。每次循环后high-low的值至少将该次循环前的值折半;于是,循环的次数最多为log(N-1)+2。(例如,若high-low=128,则在歌词迭代后high-low的最大值是64,32,16,8,4,2,1,0,-1)因此,运行时间是O(logN)。
2.欧几里得算法(辗转相除法)
计算最大公因数的欧几里得算法。两个整数的最大公因数(gcd)是同时整除二者的最大整数。
public static long gcd(long m, long n) { while (n != 0) { long rem = m % n; m = n; n = rem; } return m; }
连续计算余数直到余数是0为止,最后的非零余数就是最大公因数。例如M=1989和N=1590,则余数序列是399,393,6,3,0,从而两者的最大公因数是3。
3.幂运算
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; }
相关文章