iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言三分钟精通时间复杂度与空间复杂度
  • 232
分享到

C语言三分钟精通时间复杂度与空间复杂度

2024-04-02 19:04:59 232人浏览 独家记忆
摘要

目录一、时间复杂度1)O(n)的含义2)复杂表达式的简化3)O(n)不一定优于O(n^2)​4)递归的时间复杂度二、空间复杂度1)O(1)空间复杂度​2)​​​​​​​O(n)空间复

一、时间复杂度

1)O(n)的含义

  • 程序消耗的时间用算法的操作单元数来表示
  • 假设数据的规模为n,则用f(n)表示操作单元数的大小,而f(n)常被简化
  • O表示的是一般的情况,而不是上界或下界。并且它是在数据量级非常大的情况下所展现出的时间复杂度
  • 因为O代表的是一个一般的情况,所以当用例不同时,算法的时间复杂度不同,需要具体分析

2)复杂表达式的简化

表达式简化遵循以下两个原则:

  • 去掉常数项
  • 只保留最高项

为例分析:

  • 去掉常数项后为
  • 只保留最高项后为

不难想象,当n趋一个非常大的数量级的时候,最高项将其决定性作用。但是若常数项也是一个非常大的数量级,那我们就不可以轻易将其舍去。

3)O(n)不一定优于O(n^2)

        由上面简化法则我们可以看到,常数项是被忽略的,如,当n < 20时前者的操作单位数是小于后者的。

所以在决定使用什么算法的时候并不是算法的时间复杂度越低越好,还需要考虑数据的规模

        那为什么我们默认时间复杂度低于呢?正如前面提到的关于O的定义:它是在数据量级非常大的情况下所展现出的时间复杂度,所以我们默认前者的时间复杂度更优。

​4)递归的时间复杂度

⭐递归的时间复杂度 = 递归次数 X 每次递归的操作次数。

现在我们从一道面试题来分析时间复杂度:求x的n次方

①直观的for循环遍历


int fuc1(int n)
{
	int ret = 1;
	for (int i = 1; i < n; i++)
		ret *= i;
	return ret;
}

【分析】时间复杂度为O(n),因为操作单元数为n次​

②递归版本1


int fuc2(int n,int x)
{
	if (n == 0)
		return 1;
	if (n == 1)
		return x;
	return x * fuc2(n - 1, x);
}

【分析】递归次数为n次,每次相乘的时间复杂度为O(1),所以时间复杂度仍为O(n)

​③递归版本2​


int fuc3(int n, int x)
{
	if (n == 0)
		return 1;
	if (n == 1)
		return x;
	if (n % 2 == 1)
		return fuc3(n / 2, x) * fuc3(n / 2, x) * x;//奇数次幂的情况
	return fuc3(n / 2, x) * fuc3(n / 2, x);		   //偶数次幂的情况
}

【分析】上面代码的时间复杂度为吗?我们可以画二叉树来理解,以n = 16为例​

每一个结点都表示需要进行一次递归,因此结点数代表着递归次数,所以先我们计算二叉树结点数​

  • 一颗满二叉树的结点数根据等比数列求和公式可以求出为:​(m为二叉树深度)​
  • 二叉树深度m 计算公式​:(向下取整)​

        因为n为奇数时我们将其拆成偶数处理,如:

将深度公式代入结点总和公式我们可以得出, 节点数 = n - a(a为某个常数),所以时间复杂度还是

④递归版本3​


int fuc4(int n, int x)
{
	if (n == 0)
		return 1;
	else if (n == 1)
		return 1;
	int t = fuc4(n / 2, x);
	if (n % 2 == 1)
		return t * t * x;
	return t * t;
}

通过将递归操作抽离出来从而减少递归次数,我们真正实现了时间复杂度为​

我们再分析一下求斐波那契数列函递归解法时间复杂度:​


int fib(int n)
{
	if (n <= 0)
		return 1;
	if (n == 1)
		return 1;
	return fib(n - 1) + fib(n - 2);
}

同样的我们可以画二叉树来分析。求第k个斐波那契数,我们不难想象,我们将构造出一个深度为k的二叉树,深度为k的二叉树最多有个结点,所以我们得出该算法的时间复杂度为优化的思路和上述求x的n次方的思路一样,主要是减少递归的调用次数​


int fib(int first, int second, int n)
{
	if (n <= 0)
		return 0;
	if (n < 3)
		return 1;
	else if (n == 3)
		return first + second;
	else
		return fib(second, first + second, n - 1);
}

二、空间复杂度

1)O(1)空间复杂度​

程序占用空间不随n的变化而变化,即占用的空间是一个常数​


for(int j = 0; j < n; j++)
{
	j++;
}

程序占用的空间与n无关,上图中之涉及为j分配内存空间,是一个固定的常量​

2)​​​​​​​O(n)空间复杂度​

程序占用空间随n增长而线性增长;​


int arr[n];

3)​​​​​​​O(mn)空间 复杂度​

常常是定义一个二维集合,集合的大小与集合的长与宽相管​


int arr[row * col];

4)递归算法空间算法复杂度分析​

⭐递归算法空间复杂度 = 每次递归的空间复杂度 X 递归深度(递归调用栈的最大长度)

我们同样来分析上面提到的求斐波那契数函数的空间复杂度:​


int f(int n)
{
	if (n <= 0)
		return 1;
	if (n == 1)
		return 1;
	return f(n - 1) + f(n - 2);
}

在递归的过程中依次将f(5),f(4), f(3),f(2),f(1)压栈,每一次调用所占用的空间都为所以占用的空间为,所以上述代码的空间复杂度为​

我们再来分析递归实现的二分查找的空间复杂度​:


int binary_search(int arr[], int l, int r, int x)
{
	if (r >= l)
	{
		int mid = l + (r - l) / 2; //避免先加后除产生溢出的错误
		if (arr[mid] == x)
			return mid;
		else if (arr[mid] < x)
			return binary_search(arr, mid + 1, r ,x);
		else
			return binary_search(arr, l, mid - 1, x);
	}
	return -1;
}

每次递归所占用的空间都是一定的,所以每次递归的空间复杂度为,而递归的最大深度为,所以空间复杂度为

到此这篇关于C语言三分钟精通时间复杂度与空间复杂度的文章就介绍到这了,更多相关C语言 时间复杂度内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言三分钟精通时间复杂度与空间复杂度

本文链接: https://www.lsjlt.com/news/138312.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c语言怎么计算字符串长度
    在C语言中,可以使用内置的strlen()函数来计算字符串的长度。该函数位于string.h头文件中。以下是一个示例代码: #inc...
    99+
    2024-05-15
    c语言
  • c语言怎么判断三个数的大小
    可以通过比较三个数之间的大小关系来判断它们的大小。以下是一个示例代码: #include <stdio.h> int ...
    99+
    2024-05-15
    c语言
  • c++排序函数sort怎么使用
    在C++中,使用sort函数对容器中的元素进行排序,可以按照默认的升序排列,也可以自定义排序规则。 下面是一个简单的例子,对一个ve...
    99+
    2024-05-15
    c++
  • c++中string的compare函数怎么使用
    在C++中,可以使用string的compare函数来比较两个string对象的大小。该函数的原型如下: int compare(c...
    99+
    2024-05-15
    c++
  • c++中string的compare函数有什么用
    c++中string的compare函数用于比较两个字符串的大小关系。该函数返回一个整数值,表示两个字符串的比较结果。 具体来说,如...
    99+
    2024-05-15
    c++
  • c++中print函数的功能有哪些
    在C++中,通常使用std::cout来进行输出操作,而不是使用print函数。std::cout是C++标准库中的一个输出流对象,...
    99+
    2024-05-15
    c++
  • c语言数据结构怎么使用
    在C语言中,数据结构可以通过定义结构体来实现。以下是一些常见的数据结构的使用方法示例: 链表: #include <std...
    99+
    2024-05-15
    c语言
  • c++中print函数的用法是什么
    在C++中没有内置的print函数,但可以使用cout来输出内容到控制台。cout是C++标准库中的一个输出流对象,可以使用<...
    99+
    2024-05-15
    c++
  • c++中concept的用法是什么
    在C++20中,Concept是一种新的语言特性,用于定义类型要求和约束。Concept可以被用来约束函数模板、类模板和普通函数的参...
    99+
    2024-05-15
    c++
  • c++中concept的作用是什么
    在C++中,concept的作用是定义一种通用的约束,用于限制模板参数的类型范围。通过使用concept,可以在编译时对模板参数进行...
    99+
    2024-05-15
    c++
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作