如何选择数据结构和算法(转)

文章目录

    • 1. 时间、空间复杂度 != 性能
    • 2. 抛开数据规模谈数据结构和算法都是“耍流氓”
    • 3. 结合数据特征和访问方式来选择数据结构
    • 4. 区别对待IO密集、内存密集和计算密集
    • 5. 善用语言提供的类,避免重复造轮子
    • 6. 千万不要漫无目的地过度优化

熟知每种数据结构和算法的功能、特点、时间空间复杂度,还是不够的。工程上的问题往往都比较开放,往往需要综合各种因素,比如编码难度、维护成本、数据特征、数据规模等,最终选择一个工程的最合适解,而非理论上的最优解。

在这里插入图片描述

1. 时间、空间复杂度 != 性能

  • 复杂度不是执行时间和内存消耗的精确值
    大O表示法表示复杂度的时候,复杂度给出的只能是一个非精确量值的趋势。
  • 代码的执行时间有时不跟时间复杂度成正比
    时间复杂度是O(nlogn)的算法,比时间复杂度是O(n2)的算法,执行效率要高。前提是,算法处理的是大规模数据的情况。
  • 对于处理不同问题的不同算法,其复杂度大小没有可比性

2. 抛开数据规模谈数据结构和算法都是“耍流氓”

  • 在数据规模很小的情况下,普通算法和高级算法之间的性能差距会非常小。
    大部分情况下,我们直接用最简单的存储结构和最暴力的算法就可以了。

比如,对于长度在100以内的字符串匹配,我们直接使用朴素的字符串匹配算法就够了。如果用KMP、BM这些更加高效的字符串匹配算法,实际上就大材小用了。因为这对于处理时间是毫秒量级敏感的系统来说,性能的提升并不大。相反,这些高级算法会徒增编码的难度,还容易产生bug

3. 结合数据特征和访问方式来选择数据结构

如何将一个背景复杂、开放的问题,通过细致的观察、调研、假设,理清楚要处理数据的特征与访问方式,这才是解决问题的重点。

比如前面讲过,Trie树这种数据结构是一种非常高效的字符串匹配算法。但是,如果你要处理的数据,并没有太多的前缀重合,并且字符集很大,显然就不适合利用Trie树了。所以,在用Trie树之前,我们需要详细地分析数据的特点,甚至还要写些分析代码、测试代码,明确要处理的数据是否适合使用Trie 树这种数据结构。

再比如,图的表示方式有很多种,邻接矩阵、邻接表、逆邻接表、二元组等等。你面对的场景应该用哪种方式来表示,具体还要看你的数据特征和访问方式。如果每个数据之间联系很少,对应到图中,就是一个稀疏图,就比较适合用邻接表来存储。相反,如果是稠密图,那就比较适合采用邻接矩阵来存储。

4. 区别对待IO密集、内存密集和计算密集

  • 如果要处理的数据存储在磁盘,比如数据库中。那代码的性能瓶颈有可能在磁盘IO,而并非算法本身。这个时候,你需要合理地选择数据存储格式和存取方式,减少磁盘IO的次数

比如最终推荐人的例子。如果某个用户是经过层层推荐才来注册的,获取他的最终推荐人的时候,就需要多次访问数据库,性能显然不高。
我们知道,某个用户的最终推荐人一旦确定,就不会变动。所以,可以离线计算每个用户的最终推荐人,并且保存在表中的某个字段里。当要查看某个用户的最终推荐人的时候,访问一次数据库就可以获取到。

  • 如果数据是存储在内存中,那还需要考虑,代码是内存密集型的还是CPU密集型的。

所谓CPU密集型,简单点理解就是,代码执行效率的瓶颈主要在CPU执行的效率。我们从内存中读取一次数据,到CPU缓存或者寄存器之后,会进行多次频繁的CPU计算(比如加减乘除),CPU计算耗时占大部分。所以,在选择数据结构和算法的时候,要尽量减少逻辑计算的复杂度。比如,用位运算代替加减乘除运算等。

所谓内存密集型,简单点理解就是,代码执行效率的瓶颈内存数据的存取。对于内存密集型的代码,计算操作都比较简单,比如,字符串比较操作,实际上就是内存密集型的。每次从内存中读取数据之后,我们只需要进行一次简单的比较操作。所以,内存数据的读取速度,是字符串比较操作的瓶颈。因此,在选择数据结构和算法的时候,需要考虑是否能减少数据的读取量,数据是否在内存中连续存储,是否能利用CPU缓存预读

5. 善用语言提供的类,避免重复造轮子

大部分常用的数据结构和算法,编程语言都提供了现成的类和函数实现。比如,Java中的HashMap就是散列表的实现,TreeMap就是红黑树的实现等。除非有特殊的要求,一般直接使用编程语言中提供的这些类或函数。

这些编程语言提供的类和函数,经过无数验证过的,不管是正确性、鲁棒性,都要超过你自己造的轮子。

重复造轮子,并没有那么简单。你需要写大量的测试用例,并且考虑各种异常情况,还要团队能看懂、能维护。出力不讨好。

这也是很多高级的数据结构和算法,比如Trie树、跳表等,在工程中,并不经常被应用的原因。但这并不代表,学习数据结构和算法是没用的。深入理解原理,有助于你能更好地应用这些编程语言提供的类和函数。能否深入理解所用工具、类的原理,这也是普通程序员跟技术专家的区别。

6. 千万不要漫无目的地过度优化

一段代码执行只需要0.01秒,你非得用一个非常复杂的算法或者数据结构,将其优化成0.005秒。这种微小优化的意义也并不大。维护成本高。

要学会估算。不仅要对普通情况下的数据规模和性能压力做估算,还需要对异常以及将来一段时间内,可能达到的数据规模和性能压力做估算。这样,我们才能做到未雨绸缪,写出来的代码才能经久可用。

还有,当你真的要优化代码的时候,一定要先做Benchmark 基准测试。这样才能避免你想当然地换了一个更高效的算法,但真实情况下,性能反倒下降了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/479816.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux服务器安装cuda,cudnn,显卡驱动和pytorch超详细流程

原文链接:https://blog.csdn.net/kingfoulin/article/details/98872965 基本的环境 首先了解自己服务器的操作系统内核版本等信息: 查看自己操作系统的版本信息:cat /etc/issue或者是 cat /etc/lsb-release等命令 查看服务器显卡信息&…

自训练:超越预训练,展现强大互补特性的上分新范式!

文 | 香侬科技编 | 兔子酱背景预训练(Pre-training)模型自BERT问世以来就一发不可收拾,目前已经在自然语言理解和生成两个方面取得了突破性成就。但是,作为它的一个“兄弟”,自训练(Self-training&#xff…

论文浅尝 | 通过文本到文本神经问题生成的机器理解

论文笔记整理:程茜雅,东南大学硕士,研究方向:自然语言处理,知识图谱。Citation: Yuan X, WangT, Gulcehre C, et al. Machine comprehension by text-to-text neural question generation[J]. arXiv preprint arXiv:17…

安装paddlepaddle-GPU 报libcudnn.so和libcublas.so找不到的解决方案

第一步,查找两个的文件位置 第二步: 由于cudcun实在cuda10.0的基础上安装的,解压cudcnn的tar包之后会出现一个cuda-10.0文件夹,而不是cuda. 第三步: 在一步出现的位置找到了和libcublas.so.10对其进行了重命名就好了…

LeetCode 221. 最大正方形(DP)

文章目录1. 题目信息2. 解题1. 题目信息 在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。 示例: 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/maximal-squ…

anaconda配置虚拟环境

一般是在服务器上,创建一个自己的虚拟环境,自己来用,不影响别人的环境,也不用被别人安装环境影响。 打开终端 1.查看当前存在哪些虚拟环境 conda env list 或 conda info -e 2.创建名字为 lly_env 的虚拟环境(名字自己取一个&am…

论文浅尝 | 知识图谱推理中表示学习和规则挖掘的迭代学习方法

作者:张文,浙江大学在读博士,研究方向为知识图谱的表示学习,推理和可解释。本文是我们与苏黎世大学以及阿里巴巴合作的工作,发表于WWW2019,这篇工作将知识图谱推理的两种典型方法,即表示学习和规…

21个深度学习调参的实用技巧

文 | AI_study源 | AI算法与图像处理导读在学习人工智能的时候,不管是机器学习还是深度学习都需要经历一个调参的过程,参数的好坏直接影响着模型效果的好坏。本文总结了在深度学习中21个实用的调参的技巧,快来学习吧!这篇文章在国…

从Java程序员进阶为架构师,全套16张图概括最全技能!建议收藏!

如何从程序员进阶到架构师?今天完整的把我积累的经验和技能分享给大家! 作者:陈睿|优知学院创始人 数据结构算法程序 数据是一切能输入到计算机的信息总和,结构是指数据之间的关系,数据结构就是将数据及其之间的关系有…

Python 爬虫系列教程一爬取批量百度图片

原文地址:https://blog.csdn.net/qq_40774175/article/details/81273198 很久之前就学习了Python的爬虫了,也用来做过一些项目(主要是一些课程项目),但时间比较紧,一直没有空把它写下来,这个暑假…

论文浅尝 | 利用知识图谱嵌入和图卷积网络进行长尾关系抽取

论文笔记整理:王狄烽,南京大学硕士,研究方向为关系抽取、知识库补全。链接:https://arxiv.org/pdf/1903.01306.pdf发表会议:NAACL2019动机现有的利用远程监督进行实体关系抽取的方法大多关注于如何对训练数据进行降噪&…

人脑是怎么防止梯度消失和梯度爆炸的?

文 | 极市平台源 | 知乎问答导读梯度消失和梯度爆炸一直是深度学习的难点,而人脑有接近900亿个神经元,可以说是一个非常规模庞大的网络。那么人脑是如何防止梯度消失和梯度爆炸的?观点一作者丨冒蓝火的加特林感觉这个问题跟我的科研方向有一点…

史上最全java架构师技能图谱(下)

“java架构史上最全技能图谱分为上下两篇,这是java架构史上最全图谱下篇,包含: 大数据以及性能、设计模式、UML、中间件、分布式集群、负载均衡、通讯协议、架构设计等技术图谱等章节。 如果需要上篇内容:数结构算法、java进阶、…

Git基本指令

一、创建本地仓库进行版本控制 在工作区 local_repository 新建readme.txt文件: git init :初始化一个空的本地仓库,并在本地仓库生成了.git 文件git add readme.txt :将文件放到暂存区,表示这个文件受git管理git co…

LeetCode 21. 合并两个有序链表(单链表)

文章目录1. 题目信息2. 解题1. 题目信息 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例:输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4来源&#xff1a…

一文读懂最强中文NLP预训练模型ERNIE

基于飞桨开源的持续学习的语义理解框架ERNIE 2.0,及基于此框架的ERNIE 2.0预训练模型,在共计16个中英文任务上超越了BERT和XLNet, 取得了SOTA效果。本文带你进一步深入了解ERNIE的技术细节。 一:ERNIE 简介 1.1 简介 Google 最近提出的 BER…

BERT原理、代码、相关模型、精调技巧,看这个就够了

星标/置顶小屋,带你解锁最萌最前沿的NLP、搜索与推荐技术2018 年 10 月,由 Google 推出的 BERT 模型一鸣惊人,刷爆了各路榜单,甚至超越了人类基线分数,实现了 NLP 领域里程碑式的突破。 如今,对于 NLP 算法…

论文浅尝 | 利用 KG Embedding 进行问题回答

论文笔记整理:吴杨,浙江大学计算机学院,知识图谱、NLP方向。http://research.baidu.com/Public/uploads/5c1c9a58317b3.pdf动机本文主要针对基于知识库的问题回答中的简单问题,也就是问题的答案只涉及KG中的一跳,此类问…

想成为阿里160万年薪的P8架构师?你必须掌握如下6大技能体系!

程序设计和开发 数据结构和算法:常用数据结构,排序,检索等 面向对象编程、设计模式,掌握建模语言和建模工具:UML、MVC编程思想 高质量编码能力:重用性,低耦合,可扩展性&#xff0c…

技术动态 | 知识图谱的策展

作者:Jiaoyan Chen, Senior Researcher, Department of Computer Science, University of Oxford, Research interests: Knowledge Base, Knowledge-based Learning, Machine Learning Explanation.知识图谱在众多的领域中发挥了重要作用,比如聊天机器人…