广告
返回顶部
首页 > 资讯 > 精选 >web算法复杂度怎么理解
  • 155
分享到

web算法复杂度怎么理解

2023-06-03 16:06:59 155人浏览 泡泡鱼
摘要

本篇内容介绍了“WEB算法复杂度怎么理解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!算法学(AlGorithmics)是设计和研究算法的科

本篇内容介绍了“WEB算法复杂度怎么理解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

算法学(AlGorithmics)是设计和研究算法的科学,它的历史可比计算机科学的历史久远多了,但今天算法学却几乎全由计算机科学家实践。

算法学是一个非常广泛的领域,需要不少数学知识。当然了,并非所有计算机科学家都需要成为天才的算法学家。从算法的角度来看,大多数程序员面临的问题实际上非常简单。

但我们有时需要实现一些更复杂的东西。在这种情况下,算法方面的基本知识就会显得非常有用。我们并不要求你发明一种革命性的新算法并给出其复杂度的具体证明,但为了能够准确地使用那些在网络上或软件库中找到的算法,还是有必要接受一下“基础培训”的。

懂算法会让你更有效率,能够更好地理解你所要解决的问题,也不会写出不规范的代码:有一些代码尽管可以正常运行,但从算法的角度来看却是不合理的。一个经验不丰富的程序员可能会直接使用这些不合格的算法(他会想:“代码能运行,所以应该没什么问题”),但你因为懂算法,就能很快发现代码的问题,并改写出一个优秀得多的版本。

听我说了这些,你可能有点跃跃欲试了。下面是两个简单的对于算法复杂度的研究题,它们可以让你更准确地了解算法复杂度的作用。

寻找最大和最小的元素


问题 1:有一个正整数列表,我们想要找到列表中最大的整数。

这个问题的经典解法如下:遍历此列表,并一直保存迄今为止发现的最大元素,称其为“当前最大值”。

我们可以将此算法描述为:

一开始,“当前最大值”等于 0。我们用列表中每一个元素去和“当前最大值”做比较,如果当前遍历到的元素比“当前最大值”更大,则将“当前最大值”设为当前元素的值。在遍历完整个列表后,“当前最大值”就真的“实至名归”了。

下面我们给出此算法的一种实现,是用“世界上最好的编程语言PHP 来实现的(当然,你也可以用其他编程语言来实现):

<?php
function max($list) {
  $current_max = 0;
  foreach ($list as $item)
      if ($item > $current_max)
          $current_max = $item;
  return $current_max;
}
?>

我们可以快速验证此算法是正确的:我们只需要确认在此算法执行时,“当前最大值”总是等于到目前为止所遍历到的列表元素里最大的那个值。

我们也注意到此算法是会“结束”的,它不会陷入无限循环:此算法遍历完整个列表,然后停止。这看起来像一个不重要的细节,但实际上有一些编程语言里是可以表示无限多元素的列表的:在这种情况下,我们的算法是不正确的。

现在让我们研究此算法的复杂度。我们要考虑哪些操作呢?显然,大部分工作都在于将当前元素与“当前最大值”进行比较(毕竟,“当前最大值” current_max 的初始化(初始化为 0)并不占多少运行时间),因此我们计算“比较操作”的次数,将其作为此算法的操作数。

算法的执行时间取决于哪些参数呢?可以想见,执行时间并不依赖于列表中每个元素的值(在此,我们假设两个整数的比较时间是恒定的,不论它们的值是多少)。因此,我们用元素列表的长度 N 来量化输入。

对于一个包含 N 个元素的列表,我们要进行 N 次比较:每个元素都与“当前最大值”进行一次比较。因此,算法的时间复杂度是 O(N):它的执行时间是呈线性的,与列表的元素数目 N 成正比。

那么,此算法的空间复杂度是多少呢?此算法使用了一个列表,里面的元素占用了一定的内存空间。但是,这个列表在我们查找其最大元素之前就已经存在了,它所占用的内存空间并不是由我们的算法分配的,因此我们说此列表的元素数目 N 并不会被考虑到算法的空间复杂度的计算中,我们只考虑由我们的算法直接申请的内存。

而我们的算法直接申请的内存空间几乎可以忽略不计,因为最多就是占用了一个临时变量(current_max),用以存储“当前最大值”。因此,我们的算法所占用的内存空间不依赖于列表的长度: (我们将空间复杂度记为 O(1),表示它不依赖于 N)。

对于我们的算法,现在只剩下一个小细节要注意了:如果我们的列表是空的,那么返回的最大值将是 0。要说“一个空的列表的最大值是 0” 显然不一定是正确的:在某些情况下,如果列表是空的,最好返回一个错误。

因此我们可以改进一下我们的算法:我们不再为“当前最大值”赋初值为 0,而是以列表的第一个元素(如果该列表为空,则返回一个错误)作为“当前最大值”的初始值。然后,我们从第二个元素开始比较。

经过改进后的算法执行 N-1 次比较(因为我们不必将第一个元素与它自己进行比较)。不过,这并没有改变算法的时间复杂度:N 和 N-1 之间的时间差并不依赖于 N,它是恒定的,因此我们可以忽略它:两种算法具有相同的时间复杂度,它们都是时间线性的(时间复杂度是 O(N) )。

最后,我们注意到第二个算法也适用于负数(如果列表的所有元素都是负数,第一个算法会返回 0,这显然不正确)。因此改良后的第二个算法更通用,也更好。

当然了,查找列表中最小值的算法和查找最大值是类似的,我们就不赘述了。

寻找不重复的元素


现在我们来看第 2 个问题。

问题 2:有一个列表 1,其中包含重复项(多次出现的元素):我们想要构建一个包含与列表 1 相同元素的列表 2,但是列表 2 中每个元素只重复出现一次。

例如,列表 1 里有以下元素:

AABCDBCA

则列表 2 将包含以下元素:

ABCD

你想到解决这个问题的算法了吗?在阅读我的解决方案之前,请自己思考一下。

我的解决方案

我的算法如下:

对于给定的包含重复元素的列表 L,我们要构建一个新的列表 U(取英语 Unique(“独一无二的”)的第一个字母),列表 U 一开始是空的,我们需要往里面填充元素。我们遍历列表 L,对于列表 L 中的每一个元素,我们确认一下它是否存在于列表 U 中(可以用与之前的查找最大元素类似的算法,毕竟就是逐一比较元素嘛)。如果列表 L 中遍历到的元素还不在列表 U 中,就将这个元素添加进列表 U 中;如果已经存在于列表 U 中,就不添加。遍历完列表 L 后,列表 U 中就拥有了和列表 L 相同的元素,只是这些元素都是不重复出现的。


练习: 使用你喜欢的编程语言来实现上述从列表中提取不重复元素的算法。

复杂度

这个算法的复杂度是多少?如果你充分理解了之前查找列表最大值的算法的复杂度的计算,那么这对你来说应该很简单。

对于给定列表 L 中的每个元素,我们都会执行遍历列表 U 的操作,因此执行的操作数与列表 U 包含的元素数目有关。

但问题是:列表 U 的大小在遍历给定列表 L 的过程中会发生变化,因为我们会添加元素进列表 U。当我们遍历到列表 L 中的第一个元素时,列表 U 还是空的(因此我们不执行任何比较操作);当我们遍历到列表 L 的第二个元素时,列表 U 有 1 个元素,所以我们要再执行一个比较操作。

但是当我们遍历到列表 L 中的第三个元素时,我们就变得不是那么肯定了:如果列表 L 中的前两个元素是不相同的,它们都被添加到 U 中,在这种情况下我们要执行 2 次比较操作(将列表 L 中的第三个元素分别与列表 U 中的两个元素作比较);如果前两个元素是相同的,那么列表 L 中的第二个元素就没有被添加到列表 U 中,只执行 1 次比较操作。

正如我们的课程里已经说过的,复杂度的计算需要考虑在“最坏的情况”(worst case)下:也就是执行的操作数目最多时的复杂度。因此,我们将认为给定列表 L 的所有元素都是不相同的。

在“最坏的情况”下,我们将给定列表 L 的所有元素逐一添加进列表 U 中。假设给定列表 L 一共有 N 个元素,在遍历到给定列表 L 的第 N 个元素时,我们已经向列表 U 添加了 (N-1) 个元素了,因此这时要做 (N-1) 次比较操作。

所以我们总共要做的比较操作数是 0 + 1 + 2 + … + (N-1) 。开始时的操作数少,越到后面做的操作越多(有点像人生,出生时责任比较少,慢慢地责任越来越大,要处理的事情也越来越多,不过也说明你在成长,毕竟“能者多劳”)。

上面这一串数字相加,得到的总操作数是 N * (N - 1) / 2(这个不难,是数学里面的等差数列求和公式),由于我们在计算复杂度时考虑的是 N 很大的情况,上面的结果可以约等于 N * N / 2,即 N2 / 2 个操作。

因此,我们的算法具有 O(N2) 的时间复杂度(我们去除了常数因子 1/2)。我们也可以称 O(N2) 为“二次/平方”的复杂度(正如我们称 O(N) 具有“线性”的复杂度)。

与之前那个查找最大元素的算法比起来,现在这个算法除了速度较慢(时间复杂度较高)之外,还具有更高的空间复杂度:我们构建了一个最初不存在的列表 U(因此申请了内存空间)。

在最坏的情况下,列表 U 还具有与给定列表 L 一样多的元素:因此将为 N 个元素分配空间,这使得空间复杂度为 O(N)。之前查找最大元素的算法的空间复杂度是恒定的(O(1)),但现在这个算法的空间复杂度却是线性的(O(N))。

该算法只需要比较元素,因此被操作的元素并不一定要是整数:我们可以用相同的算法来消除单词列表中重复的单词,重复的浮点数,等等。因此,许多算法是与使用的元素的具体类型无关的。

寻找不重复的元素:另一种方法


寻找不重复的元素,其实还有另一种算法(聪明如你可能也想到了):我们可以先对给定列表 L 中的元素进行排序,使得所有重复的元素都相邻,这样排除重复元素将变得很简单。

比如给定列表 L 初始是这样的:

AABCDBCA

我们可以在构建列表 U 前,先对列表 L 进行排序,使其变成下面这样:

AAABBCCD

这样,我们之后构建列表 U 的算法就简单了。

算法如下:只需遍历排序后的列表 L,并记住最近一次遍历到的那个元素。如果当前元素与前一个元素相同,则这个元素是重复的,就不要把它包含在不重复元素的列表 U 中。

如果重复的元素彼此不相邻,则上述算法不再有效。因此我们必须先对列表进行排序。

这个新的算法的时间复杂度是什么?消除重复是在列表的单次遍历中完成的,因此是线性的( O(N))。但由于我们必须先对列表进行排序,因此第一步排序的操作也必须被考虑进这种新算法的总复杂度中。

当然了,在这里提到列表的排序还稍微有一些太早了,因为我们在之后的课程里才会讲到排序算法。

尽管目前我们还没有学习排序算法和它们的复杂度,但我还是想说一下这个新算法的复杂度问题。

事实证明,这种算法的复杂度取决于排序的复杂度:因为,排序基本上会执行 N2 个操作,这远远超过我们之后的构建列表 U 时的 N 个操作,所以整体复杂度是 O(N2)。

然而,也存在更高端的排序算法,虽然仍然执行多于 N 个操作,但比 N2 要少得多。

我们将在之后的课程里学习排序算法,目前你只需要知道这个多了一步排序的新算法比旧算法更有效,也更“高级”。

“在列表中搜索指定元素”与“找出列表中最大/小值的元素”是非常相似的算法,都是线性时间的(算法的时间复杂度是 O(N)),空间复杂度都是 O(1)。

消除列表中的重复元素的算法更复杂一些,因为最简单的算法在时间上具有平方的时间复杂度(O(N2)),其空间复杂度具有线性(O(N))。

我希望这些更具体的研究能让你确信算法学和算法复杂度还是很有用的。现在你也应该已经习惯“算法”,“时间复杂度”,“空间复杂度”这些基本概念了。

“web算法复杂度怎么理解”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: web算法复杂度怎么理解

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

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

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

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

下载Word文档
猜你喜欢
  • web算法复杂度怎么理解
    本篇内容介绍了“web算法复杂度怎么理解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!算法学(Algorithmics)是设计和研究算法的科...
    99+
    2023-06-03
  • 怎么理解Java算法复杂度
    本篇内容主要讲解“怎么理解Java算法复杂度”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解Java算法复杂度”吧!大O符号衡量时间复杂度通常使用”大O符号“。什么是大O符号?我们需要先看...
    99+
    2023-06-02
  • web算法的时间复杂度和空间复杂度是什么
    这篇文章主要介绍了web算法的时间复杂度和空间复杂度是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇web算法的时间复杂度和空间复杂度是什么文章都会有所收获,下面我们一起来...
    99+
    2022-10-19
  • 如何理解算法的复杂度
    本篇内容主要讲解“如何理解算法的复杂度”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解算法的复杂度”吧!1. Motivation - 为什么需要复杂度分...
    99+
    2022-10-19
  • 如何理解算法时间复杂度
    这篇文章主要讲解了“如何理解算法时间复杂度”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解算法时间复杂度”吧!我们可以用下面的表达式来表示:通常主要有...
    99+
    2022-10-19
  • 递归算法时间复杂度怎么算
    递归算法的时间复杂度可以通过递归树来计算。递归树是一个树形结构,表示递归算法的执行过程。树的根节点表示原始问题,每个节点表示递归调用...
    99+
    2023-05-30
    递归算法时间复杂度 递归算法
  • 怎么用JavaScript学习算法复杂度
    这篇文章给大家分享的是有关怎么用JavaScript学习算法复杂度的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。JavaScript的作用是什么1、能够嵌入动态文本于HTML页面。2、对浏览器事件做出响应。3、读...
    99+
    2023-06-14
  • C语言 超详细讲解算法的时间复杂度和空间复杂度
    目录1.前言1.1 什么是数据结构?1.2 什么是算法?2.算法效率2.1 如何衡量一个算法的好坏2.2 算法的复杂度2.3 复杂度在校招中的考察3.时间复杂度3.1 时间复杂度的概...
    99+
    2022-11-13
  • C语言中算法的时间复杂度和空间复杂度是什么
    这篇文章给大家分享的是有关C语言中算法的时间复杂度和空间复杂度是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1.前言1.1 什么是数据结构?数据结构(Data Structure)是计算机存储、组织数据的方...
    99+
    2023-06-29
  • 递归算法的时间复杂度是什么
    递归算法的时间复杂度取决于递归的深度以及每次递归的时间复杂度。如果递归的深度为n,每次递归的时间复杂度为T,那么递归算法的时间复杂度...
    99+
    2023-08-28
    递归算法
  • 算法与数据结构之如何理解时间与空间复杂度
    本篇内容介绍了“算法与数据结构之如何理解时间与空间复杂度”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!写在...
    99+
    2022-10-19
  • 怎么计算并测量ABAP及Java代码的环复杂度
    这篇文章主要介绍“怎么计算并测量ABAP及Java代码的环复杂度”,在日常操作中,相信很多人在怎么计算并测量ABAP及Java代码的环复杂度问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么计算并测量ABAP...
    99+
    2023-06-04
  • LRU算法怎么理解
    本篇内容介绍了“LRU算法怎么理解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!01、前言我们常用缓存提升数据查询速度,由于缓存容量有限,当...
    99+
    2023-06-16
  • 怎么理解Java优先遍历和广度优先遍历算法
    这篇文章主要讲解了“怎么理解Java优先遍历和广度优先遍历算法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Java优先遍历和广度优先遍历算法”吧!深度优先遍历主要思路是从图中一个未...
    99+
    2023-06-16
  • 怎么理解BiLSTM和CRF算法
    本篇内容介绍了“怎么理解BiLSTM和CRF算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.前言给定...
    99+
    2022-10-19
  • 怎么理解PostgreSQL中Clock Sweep算法
    本篇内容介绍了“怎么理解PostgreSQL中Clock Sweep算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能...
    99+
    2022-10-18
  • 怎么理c语言解递归算法
    这篇文章主要讲解了“怎么理c语言解递归算法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理c语言解递归算法”吧!算法思路大家都知道,一个方法自己调用自己...
    99+
    2022-10-19
  • 怎么理解DIV自适应高度写法
    这篇文章给大家介绍怎么理解DIV自适应高度写法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。DIV+CSS设计有很多值得学习的地方,这里和大家重点讨论一下DIV自适应高度的写法,希望本...
    99+
    2022-10-19
  • JavaScript数据结构与算法怎么理解
    本篇内容主要讲解“JavaScript数据结构与算法怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript数据结构与算法怎么理解”吧!前言数据结构与算法这个词相信大家都听过、...
    99+
    2023-07-02
  • 怎么理解散列算法在C# 加密中的应用
    怎么理解散列算法在C# 加密中的应用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。散列算法是C# 加密中经常会用到的方法,那么什么是散列算法呢?它的作用是如何实现的呢?那么...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作