在了解时间复杂度和空间复制度之前需要了解一下什么是数据结构与算法
1.1什么是数据结构?
数据结构是计算机存储、组织数据的方式。(简单理解就是计算机程序中会有许多类型的数据需要被存储,而数据结构就是研究要怎么存储这些不同的数据。)
1.2什么算法?
算法就是定义良好的计算过程,它取一个或一组的值作为输入,并产生一个或一组值作为输出。(简单来说算法类似数学中一系列的计算步骤,用来将输入的数据转化成输出结果。)
1.3大O的渐进表示法
O()括号里面的数表达的是这个算法的量级,大O是一个估算,并不是准确的执行次数。
推导大O阶方法:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项系数存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
2.时间复杂度
时间复杂度就是算法中的基本操作的执行次数,用O(F(N))表示,其中F(N)代表的就是算法的基本运行次数。(注意时间复杂度不计算时间,计算大概的运行次数。)
2.1简单来几个例子
实例一
//实例一
void Func(int n)
{
int count = 0;
for (int k = 0; k < 2 * n; k++)
{
//这里count执行了2n次
count++;
}
int m = 100;
while (m--)
{
//这里count执行了100次
count++;
}
}
分析:实例一基本操作执行了2n + 100 次,时间复杂度为O(2n + 100),但当n的值趋近于无穷大是n 的系数和后面的常数就可以省略,所有时间复杂度为O(n)。
实例二
//实例二
void Func1()
{
int m = 100;
while (m--)
{
//这里count执行了100次
count++;
}
}
分析:实例二基本操作执行了100次,是一个常数,所以它的时间复杂度为常数阶,即O(1)。
实例三
//实例三
void BubbleSort(int * arr, int size)
{
int flag = 0;
int temp = 0;
//冒泡排序的轮数为 size - 1
for (int i = 0; i <= size - 1; i++)
{
//冒泡排序每轮的比较次数为 size - i - 1
for (int j = 0; j < size - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 1;
}
}
if(flag == 0)
break;
}
}
分析:冒泡排序的执行次数其实就是一个等差数列F(N) = 1 + 2 ... + N - 1。那么它的时间复杂度就是O(n ^2),最好的情况就是传入的数组就是一个有序数组那么它的时间复杂度就为O(n)。
实例四
//实例四
int BinarySearch(int * arr, int size, int x)
{
int mid = 0;
int left = 0;
int right = size - 1;
while (left <= right)
{
mid = (left + right) / 2;
if (arr[mid] > x)
{
right = mid;
}
else if (arr[mid] < x)
{
left = mid;
}
else
{
return mid
}
}
return -1;
}
分析:二分查找的本质为每查找一次,查找的范围就缩小一半,直到范围缩小到1。那么就可以知道 2^x = n(其中x为执行的次数,n为数组的大小) ,那么x = log2 n。所有它的时间复杂度为O(log2 n)。
实例五
//实例五
int Factorial(int n)
{
return n < 2 ? n : Factorial(n - 1) * n;
}
分析:利用递归求n!递归的基本执行次数:递归次数 * 每次递归函数的次数。所有它的基本操作执行了n次,时间复杂度为O(n)
3.空间复杂度
空间复杂度与时间复杂度都是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 ,也就是额外占取的空间的大小。(注意空间复杂度不计算空间,计算大概定义的变量个数。)也用大O的渐进表示法。
3.1来简单的例子
实例一
//实例一
int Factorial(int n)
{
return n < 2 ? n : Factorial(n - 1) * n;
}
分析:
实例二
//实例二
int BinarySearch(int * arr, int size, int x)
{
int mid = 0;
int left = 0;
int right = size - 1;
while (left <= right)
{
mid = (left + right) / 2;
if (arr[mid] > x)
{
right = mid;
}
else if (arr[mid] < x)
{
left = mid;
}
else
{
return mid;
}
}
return -1;
}
分析:二分查找的算法中,函数的形参作用范围就是在这个函数范围内,所有这个算法大概开辟了6个变量,它的空间复杂度就是O(1)。