复杂度
时间复杂度
常见时间复杂度为:
常量阶O(1),对数阶O(logN),线性阶O(n),线性对数阶O(nlogN),平方阶O(n2)
非常用算法时间复杂度,非多项式量级:
指数阶O(2n),阶乘阶O(n!)
O(logN),O(nlogN),例:
i=1; while (i <= n) { i = i * 2; }
复杂度为O(log2N),记为O(logN)。
O(m+n),O(m*n),例:
int cal(int m, int n) {
int sum_1 = 0;
int i = 1;
for (; i < m; ++i) {
sum_1 = sum_1 + i;
}
int sum_2 = 0;
int j = 1;
for (; j < n; ++j) {
sum_2 = sum_2 + j;
}
return sum_1 + sum_2;
}
因为m和n无法判定量级,不能以常数形式省略,所以复杂度为O(m+n)。
最好、最坏情况时间复杂度
指的是最理想、最糟糕情况下,执行这段代码的时间复杂度。
平均情况时间复杂度、期望时间复杂度
将每种情况下所需要的复杂度因数累加,除以可能发生的情况数量,即为平均时间复杂度。
在计算平均时间复杂度时将每种情况的概率也加进去,即为加权平均时间复杂度或期望时间复杂度。
均摊时间复杂度
将复杂的操作均摊到其他操作内,是一种特殊的平均时间复杂度。
// array表示一个长度为n的数组
// 代码中的array.length就等于n
int[] array = new int[n];
int count = 0;
void insert(int val) {
if (count == array.length) {
int sum = 0;
for (int i = 0; i < array.length; ++i) {
sum = sum + array[i];
}
array[0] = sum;
count = 1;
}
array[count] = val;
++count;
}
在这个程序中,当array满了之后在进行插入要将所有记录的sum值放到array[0]中,然后指向array头部重新插入。
在这个情况下,当数组占满之后进行一次O(n),随后每次插入都是O(1)直到再次占满。
均摊时间复杂度:(n+(n-1)*1)/n = O(1)
空间复杂度
O(1),O(n),O(n2),例:
void print(int n) {
int i = 0;
int[] a = new int[n];
for (i; i <n; ++i) {
a[i] = i * i;
}
for (i = n-1; i >= 0; --i) {
print out a[i]
}
}
仅申请了一个a的空间,空间复杂度为O(n)。
问题
// 全局变量,大小为10的数组array,长度len,下标i。
int array[] = new int[10];
int len = 10;
int i = 0;
// 往数组中添加一个元素
void add(int element) {
if (i >= len) { // 数组空间不够了
// 重新申请一个2倍大小的数组空间
int new_array[] = new int[len*2];
// 把原来array数组中的数据依次copy到new_array
for (int j = 0; j < len; ++j) {
new_array[j] = array[j];
}
// new_array复制给array,array现在大小就是2倍len了
array = new_array;
len = 2 * len;
}
// 将element放到下标为i的位置,下标i加一
array[i] = element;
++i;
}
最好情况时间复杂度为O(1),最坏情况时间复杂度为O(n),均摊时间复杂度为O(1)。