一、 概念的引入
对于一个问题有很多种算法,那么如何衡量哪一种方法最有效呢?一般从两个方面来衡量:一个是时间效率,即算法处理数据时所花费的时间,用时间复杂度来衡量;另一个是空间效率,即算法所需求的存储量的大小,用空间复杂度来表示。
一般认为时间效率更重要。
二、时间复杂度
对于解决同一个问题的算法,执行时间短的但当然要比执行时间长的时间效率高,在此我们分析影响算法执行时间的各种因素,从而估算出算法的执行时间。
一般用算法中语句被执行的次数来表示算法的时间复杂度
三、空间复杂度
算法的空间复杂度就是程序运行时所占用的存储空间
一般只统计数据部分所占用的存储空间
下面举例说明:二分查找的非递归实现
int bin_search(int arr[], int key, int left, int right)
{
while (left <= right)
{
int mid = (left&right)+(left^right)>>1;
if (key > arr[mid])
{
left = mid + 1;
}
if (key < arr[mid])
{
right = mid - 1;
}
else
return mid;
}
return -1;
}
二分查找的实现机理如下:
首先确定待查找区间的中间位置mid=(left+right)/2,然后把待查找元素key与中间位置上的元素arr[mid]进行比较,比较的结果有以下三种情况:
(1)key=arr[mid],说明中间位置就是要查找的位置,返回中间位置的下标mid;
(2)key>arr[mid],说明要查找的位置在后半部分,则移动区间的左下标left,使left=(left+right)/2+1,然后在新的区间进行查找;
(3)key< arr[mid],说明要查找的位置在前半部分,则移动区间的右下标right,使right=(lef+right)/2-1,然后在新的区间进行查找;
在这里时间复杂度就是while的循环次数k,而每循环一次就会排除掉目前一半的数字,如果总共有n个数,那我们可以得到这样一个公式 2^k=n 则 k=log2n,所以它的时间复杂度就为0(log2n);空间复杂度为0(1)。
我们再来看一个例子:斐波那契数列的非递归实现
int Fib(int n)
{
if (n < 2)
return n;
int pre = 0;
int cur = 1;
int next;
for (int i = 2; i <= n; i++)
{
next = cur + pre;
pre = cur;
cur = next;
}
return next;
}
在上述代码中for循环被执行了n-1次,因此该算法的时间复杂度为0(n);空间复杂度为0(1)。
四、递归算法的时/空间复杂度
1、递归算法的时间复杂度为:递归总次数每次递归数*
2、递归算法的空间复杂度为:对象的个数
接下来举例说明:斐波那契数列的递归实现
int Fib(int n)
{
if (n < 2)
return n;
return Fib(n - 1) + Fib(n - 2);
}
int Fib(int n)//简洁版
{
return n < 2 ? n : Fib(n - 1) + Fib(n - 2);
}
在上述递归算法中:递归的总次数为2^n次,每次递归的次数为一个常数,因此它的时间复杂度为0(2^n);由于它最多占用n个空间,因此空间复杂度为0(n)。