时间复杂度&空间复杂度

我们编过不少代码,起初学习的时候我们习惯性的认为,只要代码能正确的运行就ok啦~很少考虑代码的优化带来的好处。今天说一下影响代码性能的两个重要指标--时间复杂度&空间复杂度。

时间复杂度:就是函数(指数学中的函数),具体执行的操作次数。通常用渐进表达式O()来表示。

空间复杂度:对象的个数。占用的空间。

算法分析一般分为三类:最坏情况、平均情况、最好情况。

算法分析要保持大局观,忽略掉常数,关注增长最快的表达式。

我们通常见到的算法的时间复杂度有:

斐波那契数列 (递归:O(2^N)非递归:O(N)

冒泡:O(N^2)

选择:O(N^2)

插入:O(N^2)

这里,主要举两个例子加以说明:

例子1:斐波那契数列


这就是著名的斐波那契数列啦。

下面讲讲斐波那契数列的两种算法,并剖析时间复杂度。

(1)递归算法

<span style="font-size:18px;">#include<iostream>
using namespace std;
#include<assert.h>

unsigned long long Fib(long long n)
{
	assert(n >= 0);
	return n < 2 ? 1 : Fib(n-1)+Fib(n-2);
}
int main()
{
	cout<<Fib(5)<<endl;
	return 0;
}</span>
斐波那契数列的递归算法:由于每一步计算都调用两次递归,即Fib(n-1)= Fib(n-2)+ Fib(n-3) = Fib(n-3)+Fib(n-4)+Fib(n-4)+Fib(n-5)=...  这样下来,就相当于二叉树,所以其时间复杂度为O(2^N),空间复杂度为O(N)。

(2)非递归算法

#include<iostream>
using namespace std;
unsigned long long Fib(long long n)
{
	long long s0 = 0;
	long long s1 = 1;
	long long s = 0;
	for(int i = 0; i < n;i++)
	{
		s1 = s0+s1;
		s0 = s1-s0;	
	}
	return s1;
}

int main()
{
	cout<<Fib(5)<<endl;
	return 0;
}
非递归算法只是在for循环里边数值的相互转换,其时间复杂度为O(N),空间复杂度为O(N)。

例子2:二分查找算法

二分查找的基本思想是将n个元素分成大致相等的两部分,a[n/2]与data做比较,如果data=a[n/2],则找到data,算法中止;如果data<a[n/2],则只要在数组a的左半部分继续搜索data,如果data>a[n/2],则只要在数组a的右半部搜索data.

(1)非递归算法

int BinaryFind(int arr[],int size,int data)
{
	int left = 0;
	int right = size-1;
	while(left <= right)        //区间[]
	{
		int mid = left-(left-right)/2;
		if(arr[mid] > data)
		{
			right = mid-1;
		}
		else if(arr[mid] < data)
		{
			left = mid+1;
		}
		else
		{
			return mid;
		}
	}
<span style="white-space:pre">	</span>return -1;
}
int main()
{
	int arr[] = {1,3,5,7,9};
	int size = sizeof(arr)/sizeof(arr[0]);
	cout<<BinaryFind(arr,size,5)<<endl;
	return 0;
}

说起二分查找的非递归算法,我们还有另外一种实现。(要特别注意)

int BinaryFind(int arr[],int size,int data)
{
	int left = 0;
	int right = size;          //区间[)
	while(left < right)
	{
		int mid = left-(left-right)/2;
		if(arr[mid] > data)
		{
			right = mid;
		}
		else if(arr[mid] < data)
		{
			left = mid+1;
		}
		else
		{
			return mid;
		}
	}
<span style="white-space:pre">	</span>return -1;
}
int main()
{
	int arr[] = {1,3,5,7,9};
	int size = sizeof(arr)/sizeof(arr[0]);
	cout<<BinaryFind(arr,size,5)<<endl;
	return 0;
}
while循环循环的次数就是时间复杂度,即时间复杂度为O(LgN),空间复杂度为O(N)。

(2)递归算法

int BinaryFind_R(int arr[],int data,int left,int right)
{
	if(left <= right)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>int mid = left-(left-right)/2;
<span style="white-space:pre">		</span>if(arr[mid] > data)
<span style="white-space:pre">			</span>BinaryFind_R(arr,data,left,mid-1);
<span style="white-space:pre">		</span>else if(arr[mid] < data)
<span style="white-space:pre">			</span>BinaryFind_R(arr,data,mid+1,right);
<span style="white-space:pre">		</span>else
<span style="white-space:pre">			</span>return mid;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>else
<span style="white-space:pre">		</span>return -1;
}
int main()
{
	int arr[] = {1,3,5,7,9};
	int size = sizeof(arr)/sizeof(arr[0]);
	int left = 0;
	int right = size - 1;
	cout<<BinaryFind_R(arr,6,left,right)<<endl;
	return 0;
}
递归时间复杂度为O(LgN)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值