关于时间复杂度和空间复杂度的计算

本文详细介绍了算法的时间复杂度和空间复杂度,解释了如何通过计算基本操作次数来衡量算法效率,并给出了具体的例子,如二分查找及斐波那契数列的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

衡量一个算法的复杂度:
  • 时间复杂度

  • 空间复杂度

  • 算法的时间复杂度和空间复杂度合称为算法的复杂度

时间复杂度

一般来说,一个算法执行所消耗的时间从理论上是算不出来的,只有通过上机运行才能测试出来。当然,我们也没
必要知道一个算法它具体执行的时间是多少,而我们又知道,一个算法花费的时间与算法中语句的执行次数是成正
比的。哪个算法语句执行的次数多,它花费的时间就多。
void Test(int n)
{
	int count = 0;
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < n; j++)
		{
			count++;
		}
	}
	for(int k = 0; k < 2*n; k++)
	{
		count++;
	}
	
	int icount = 10;
	while(icount--)
	{
		count++;
	}

}
语句的总执行次数:f(n)=n^2 + 2*n + 10

时间复杂度实际上就是一个函数,该函数计算的是执行基本操作的次数

大O渐进表示法

一个算法语句总的执行次数是关于问题规模N的某个函数,记为分f(N),N称为问题的规模。语句总的执行次数
记为T[N],当N不断变化时,T[N]也在变化,算法的执行次数的增长速率和f(N)的增长速率相同。
则T[N]=O(f(N)),称O(f(N))为时间复杂度的O渐进表示法。

空间复杂度

一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要
的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据
外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空
间包括以下两部分。  
(1)固定部分。这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间
)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
(2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法
有关。

一个算法所需的存储空间用f(n)表示。S(n)=O(f(n))  其中n为问题的规模,S(n)表示空间复杂度。
空间复杂度:函数中创建对象的个数关于问题规模函数表达式,一般情况用O的渐进表示法表示。

int Bin_search(int arr[], int len, int x)  
{  
	//二分法查找,返回数据在数组中对应的下标值,若不存在,返回-1
	//以循环方式实现
    int left = 0;  
    int right = len - 1;  
    int mid = 0;  
    while (left <= right)  
    {  
        mid = left + (right - left) / 2;  
        if (arr[mid] == x){ 
            return mid;  
        }  
        else if (arr[mid] < x){
            left = mid + 1;  
        }  
        else{
            right = mid - 1;  
        }  
    }
    return -1;  
}  
int main(void)  
{  
    int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
    int len = sizeof(arr) / sizeof(arr[0]);  
    printf("%d\n", Bin_search(arr, len, 5));  
    return 0;  
} 
int Binary_search(int arr[], int left, int right, int x)
{
	//二分法查找,递归方式实现
	int mid = left + ((right-left)>>1);
	while (arr[mid] != x)
	{
		if (arr[mid] < x){
			left = mid + 1;
			mid = left + (right - left) / 2;
			Binary_search(arr, left, right,x);
		}
		else{
			right = mid - 1;
			mid = left + (right - left) / 2;
			Binary_search(arr, left, right,x);
		}
	}
	return mid;
}
int main()
{
	int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int len = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = len - 1;
	printf("%d\n", Binary_search(arr,left, right, 3));
	printf("%d\n", Binary_search(arr, left, right,10));
	system("pause");
	return 0;
}
  • 非递归方式:时间复杂度O(log2(n))空间复杂度O(3)
  • 递归方式:时间复杂度O(log2(n))空间复杂度O(1)

下面是斐波那契数列的递归方式与非递归方式的实现:

#define N 20
int main(void)
{
	int f0=1,f1=1,fn,i;
	printf("%4d%4d",f0,f1);
	for(i=0;i<N;i++)
	{
		fn=f0+f1;
		printf("%9d",fn);
		f0=f1;
		f1=fn;
	}
	return 0;
 } 
int fib(int n)
{
	if(n <= 2)
		return 1;
	else
		return fib(n-1)+fib(n-2);
}
  • 非递归方式:时间复杂度O(n)空间复杂度O(4)
  • 递归方式:时间复杂度O(2^n) 空间复杂度O(1)

递归方式的优化算法(尾递归)

http://www.nowamagic.net/librarys/veda/detail/2325

long Fib(long first,long second,long n)
{
	if(N < 3)
		return 1;
	if(n == 3)
		return first + second;
	return Fib(second,first+second,n-1);
}
这样,时间复杂度便降到了O(n).

生活允许我们撒娇,但不可以任性,因为。。。任性往往要付出足够的代价。


### 回答问题 计算时间复杂度空间复杂度分析算法性能的重要部分。以下是详细解释。 --- #### 时间复杂度 时间复杂度描述了算法运行时间与输入规模之间的关系。通常用大O符号表示。 1. **常数时间操作**:如果一个算法的执行步骤不随输入规模变化,其时间复杂度为 $ O(1) $。 2. **线性时间操作**:如果算法的执行步骤与输入规模成正比,其时间复杂度为 $ O(n) $。 3. **平方时间操作**:如果算法的执行步骤与输入规模的平方成正比,其时间复杂度为 $ O(n^2) $。 4. **对数时间操作**:如果算法每次将问题规模减半(如二分查找),其时间复杂度为 $ O(\log n) $。 5. **线性对数时间操作**:如果算法在每层递归中处理所有元素,并且递归深度为 $ \log n $,其时间复杂度为 $ O(n \log n) $。 以下是一个示例代码及其时间复杂度分析: ```python def example_function(n): total = 0 # O(1) for i in range(n): # O(n) for j in range(n): # O(n) total += 1 # O(1) return total # O(1) # 总时间复杂度: O(n * n) = O(n^2) ``` 上述代码中: - 外层循环执行 $ n $ 次。 - 内层循环也执行 $ n $ 次。 - 每次循环内执行的操作为常数时间 $ O(1) $。 - 因此总的时间复杂度为 $ O(n^2) $。 --- #### 空间复杂度 空间复杂度描述了算法所需的额外存储空间与输入规模之间的关系。 1. **常数空间复杂度**:如果算法只使用固定数量的额外变量,其空间复杂度为 $ O(1) $。 2. **线性空间复杂度**:如果算法需要为每个输入元素分配额外空间,其空间复杂度为 $ O(n) $。 3. **递归空间复杂度**:递归调用栈的深度决定了空间复杂度。 以下是一个递归函数的空间复杂度分析: ```python def factorial(n): if n == 0: return 1 # O(1) else: return n * factorial(n - 1) # O(n) # 总空间复杂度: O(n),因为递归深度为 n ``` 上述代码中: - 每次递归调用都会占用一定的栈空间。 - 递归深度为 $ n $,因此空间复杂度为 $ O(n) $。 --- ### 示例代码及解释 以下是一个快速排序的实现及其时间复杂度空间复杂度分析: ```python def quick_sort(arr): if len(arr) <= 1: # O(1) return arr pivot = arr[len(arr) // 2] # O(1) left = [x for x in arr if x < pivot] # O(n) middle = [x for x in arr if x == pivot] # O(n) right = [x for x in arr if x > pivot] # O(n) return quick_sort(left) + middle + quick_sort(right) # 递归调用 # 时间复杂度分析: # 最优情况:每次划分均匀,递归深度为 log(n),每层比较次数为 n,总时间为 O(n log n)。 # 最差情况:每次划分极不均匀(如已排序数组),递归深度为 n,总时间为 O(n^2)。 # 平均情况:O(n log n)。 # 空间复杂度分析: # 快速排序是原地排序算法,但递归调用栈会占用额外空间。 # 最优情况:递归深度为 log(n),空间复杂度为 O(log n)。 # 最差情况:递归深度为 n,空间复杂度为 O(n)。 ``` 上述代码中: - `quick_sort` 函数通过递归实现快速排序。 - 在最优情况下,每次划分均匀,递归深度为 $ \log n $,每层比较次数为 $ n $,总时间为 $ O(n \log n) $。 - 在最差情况下,每次划分极不均匀(如已排序数组),递归深度为 $ n $,总时间为 $ O(n^2) $。 - 空间复杂度由递归调用栈决定,最优情况下为 $ O(\log n) $,最差情况下为 $ O(n) $。 --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值