数据结构与算法分析
文章平均质量分 97
流云IoT
这个作者很懒,什么都没留下…
展开
-
数据结构与算法分析(十八)--- 如何使用动态规划高效寻找最优解?
对于多阶段决策问题,我们使用回溯剪枝算法虽然可以穷举所有可行解,但复杂度太高阶。现实问题通常只关注最优解,针对多阶段决策最优解问题,我们可以使用动态规划算法大幅降低求解复杂度。动态规划的核心是划分阶段和可供决策的状态,然后找到阶段递推的状态转移方程,以便从初始状态递推到目标最优解。由于动态规划后面阶段的最优解通常跟前一阶段多个状态相关,因此存在大量的重叠子问题,通常使用备忘录或状态转移表解决重叠子问题重复求解的问题。如果后面阶段的最优解跟前面阶段无关,只需要选择最快逼近目标值的状态分支,可用贪心算法更高效。原创 2021-01-15 22:56:18 · 2075 阅读 · 0 评论 -
数据结构与算法分析(十七)--- 怎么用回溯剪枝高效穷举所有可行解?
当我们遇到一个比较复杂的问题时,通常会想到将一个复杂的问题分解为多个简单的等价子问题去解决。关键是如何分解复杂问题呢?我们可以从两个大的维度去分解:一个是从空间维度上将原大规模问题分解为多个等价的小规模子问题,再把容易求得的小规模子问题的解合并即可得到原大规模问题的解,这就是分治算法;另一种是从时间维度上将原多阶段决策问题分解为多个等价的单阶段决策子问题,再按照DFS 深度优先遍历顺序尝试所以的决策组合,所有满足约束条件的解的组合共同构成原多阶段决策问题的解,这就是回溯剪枝算法,本文以排列组合为例介绍其原理原创 2021-01-10 23:20:29 · 1498 阅读 · 2 评论 -
数据结构与算法分析(十六)--- 如何设计更高效的字符串匹配算法?(BF + RK + KMP + BMH)
字符处理操作中最常用的是字符串匹配查找算法,本文从最基础的Brute Force 匹配算法开始,分析可能对其的优化方向,就像将基础排序算法优化为归并、快速等高级排序算法一样精彩。首先,从字符比较过程入手,借助哈希值唯一标识的作用,将模式串比较时间从O(m)降低到O(1)。然后,充分利用前面已经比较过的匹配信息,让主串游标不回退,将整个文本串比较时间从O(m*n) 降低到O(n)。最后,利用字符匹配自身的规律,从后往前寻找坏字符,跳过跟主串坏字符不可能匹配的情况,将最好情况时间复杂度提升到O(n/m)。原创 2020-12-20 16:55:19 · 1861 阅读 · 0 评论 -
数据结构与算法分析(十五)--- String 和Regex 支持的字符处理操作(C++11)
字符处理是计算机的核心任务之一,各种编程语言也为字符处理提供了丰富的库函数。由于字符处理中查找匹配操作很常用,C++ 为此设计了string class 和regex class,以保证整个字符串复制传递的最优化。本文介绍了string class 支持的字符串创建、赋值、销毁操作,元素访问、容量管理操作,字符序列比较、新增、删除、替换操作,字符数值转换操作,查找、匹配操作等。C++ 提供了regex class 允许开发者使用正则表达式实现更复杂的字符序列查找、匹配、替换、分割操作。原创 2020-12-15 21:57:02 · 1095 阅读 · 0 评论 -
数据结构与算法分析(十四)--- 字符串和字符处理函数库(C11)
计算机的两大核心任务是数值计算和字符处理,分别对应数学语言和自然语言,各种计算机编程语言也分别为数值计算和字符处理提供了丰富的库函数。本文从字符编码与字符类型开始,介绍常用的字符串和字符数组操作函数,包括字符类型识别、大小写转换,数值格式与字符串格式的互相转换,字符串和字符数组的比较、拼接、复制替换、查找匹配、分割等操作。原创 2020-12-11 00:54:31 · 1070 阅读 · 0 评论 -
数据结构与算法分析(十三)--- 集合与映射 + Set/Map容器(C++11)
一、集合与映射人们把一堆东西放到一起,就称之为集合了。一般来讲,集合是具有某种特性的事物的整体,或是一些确认对象的汇集,构成集合的事物或对象称作元素或是成员。集合的元素可以是任何事物,集合具有无序性、互异性、确定性等特性。在数学上,我们可以把映射看作是集合与集合之间的一种对应关系,比如函数实际上就是数的集合到数的集合之间的映射关系。计算机更擅长处理数字编号,我们的大脑更擅长处理概念词汇,因此我们经常需要通过某个关键词key来查询一组数据的信息value,于是就把这种映射关系抽象为一个数据结构:键值对。原创 2020-01-16 16:39:13 · 2578 阅读 · 0 评论 -
数据结构与算法分析(十二)--- 怎么实现并用好一个堆或优先队列?
一、如何理解堆?如果采用类似锦标赛的方法排出了一、二、三名来,第一大的数字可以完全按照锦标赛淘汰制的方式来。但是第二大的数字,就需要从所有与最大数字比较过被淘汰的数字中,再次比较选择才能确定,当第二大的数字确定后,就可以用这种方法找到第三大的数字了。如果我们只需要选出第一名,这种算法的复杂度只有O(N),如果还需要选出第二名,则额外增加O(logN)次计算就可以了,对第三名也是如此。也就是说,锦标赛排序算法在从N个选手中选出K个选手的事情中特别快。原创 2020-01-13 20:42:30 · 851 阅读 · 2 评论 -
数据结构与算法分析(十一)--- 平衡二叉树 + 红黑树
一、什么是平衡二叉查找树发明平衡二叉查找树这类数据结构的初衷是,解决普通二叉查找树在频繁的插入、删除等动态更新的情况下,出现时间复杂度退化的问题。所以,平衡二叉查找树中“平衡”的意思,其实就是让整棵树左右看起来比较“对称”、比较“平衡”,不要出现左子树很高、右子树很矮的情况。AVL 树是一种高度平衡的二叉树,所以查找的效率非常高,但是,有利就有弊,AVL 树为了维持这种高度的平衡,就要付出更多的代价。红黑树只是做到了近似平衡,并不是严格的平衡,在维护平衡的成本上,要比 AVL 树要低。原创 2020-01-11 18:43:13 · 1032 阅读 · 0 评论 -
数据结构与算法分析(十)--- 二叉树的本质与实现 + 递归树与决策树应用
一、为何要有二叉树?世界上有什么样的问题,就有什么样的工具,或者说工具的发明是针对问题来的。在计算机中,由于经常要做的事情是判断真假、比较大小、排序、挑选最大值这类的操作,而它们在计算机的世界里又如此重要,当然也就值得为这些事情专门设计一种数据结构这种数据结构被称为二叉树。二叉树虽然是一种抽象的东西,在自然界中并不存在,但是它却浓缩了自然界很多事物的共性,那就是分叉、层层递进和有序。而针对这些共性,科学家们又总结出一些具有普遍性的算法,能够回过头来,应用到各种实际问题中。原创 2020-01-09 00:29:55 · 2324 阅读 · 0 评论 -
数据结构与算法分析(九)--- 哈希算法能用来干啥?
一、什么是哈希算法哈希算法的定义和原理非常简单,基本上一句话就可以概括了。将任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规则就是哈希算法,而通过原始数据映射之后得到的二进制值串就是哈希值。哈希算法的应用非常非常多,这里选了最常见的七个,分别是安全加密、唯一标识、数据校验、散列函数、负载均衡、数据分片、分布式存储。原创 2020-01-01 20:17:14 · 2552 阅读 · 0 评论 -
数据结构与算法分析(八)--- 如何实现并用好一个散列表?
一、如何快速完成搜索这种可以将关键词key映射为数组下标的函数称作散列(hash)函数,借助hash函数保存key--value索引条目的数组称为散列表(hash table)。散列表的插入、删除、查找或替换操作都需要两步:先通过hash函数将关键词key映射为数组下标,再通过数组下标访问关键字key对应的元素值value。散列表的插入、删除、访问或替换时间复杂度都是O(1)。散列表并不是线性表,可以把散列表看作一个元素集合。原创 2020-01-01 13:15:14 · 1002 阅读 · 0 评论 -
数据结构与算法分析(七)--- 排序算法分析 + 排序优化
一、如何分析一个排序算法1.1 排序算法的执行效率对于排序算法执行效率的分析,我们一般会从这几个方面来衡量: - 最好、最坏、平均情况时间复杂度 - 时间复杂度的系数、常数 、低阶 - 比较、交换或移动的次数1.2 排序算法的内存消耗1.3 排序算法的稳定性原创 2019-12-26 00:45:12 · 1649 阅读 · 0 评论 -
数据结构与算法分析(四)--- 时间与空间复杂度
一、复杂度分析数据结构和算法本身解决的是“快”和“省”的问题,即如何让代码运行得更快,如何让代码更省存储空间。所以,执行效率是算法一个非常重要的考量指标。那如何来衡量你编写的算法代码的执行效率呢?这里就要用到一把衡量标尺:时间、空间复杂度分析。大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),简称时间复杂度。原创 2019-12-23 23:56:19 · 865 阅读 · 0 评论 -
数据结构与算法分析(三)--- 队列、栈的实现与应用
一、队列的实现想要理解队列很简单,因为它的性质和我们日常生活中的排队很类似,线性、先到先处理、后到排末尾。很显然,队列也是一种线性表,但比线性表的要求更严格,线性表可以对中间的元素进行访问和操作,队列则只能从首尾两端访问或操作元素,队列是一种操作受限的线性表,队列的所有特性都可以由线性表实现。要理解栈也不难,弹匣只有一个子弹出入口,弹匣中有弹簧和卡子,我们最先装填进弹匣的子弹(可称为”入栈“或”压栈“)最后从弹匣中弹出(可称为”出栈“或”弹栈“),可谓是”先到进栈底,后到压上头“。原创 2019-12-23 22:54:32 · 1165 阅读 · 0 评论 -
数据结构与算法分析(二)--- STL简介 + 线性表容器(C++11)
STL是由一些可适应不同需求的集合类和一些能够在这些数据集合上运作的算法构成,STL内的所有组件都由模板构成,所以其元素可以是任意类型。STL组件包括以下部分: - 容器(container):用来管理某类对象的集合,容器可以是array、list、set、map等; - 迭代器(iterator):用来在一个对象集合内遍历元素,这个对象集合或许是个容器,或许是容器的一部分; - 算法(algorithm):用来处理集合内的元素,它们可以出于不同的目的而增、删、改、查、排序、使用元素。原创 2019-12-19 19:18:43 · 2251 阅读 · 0 评论 -
数据结构与算法分析(一)--- 数据结构的本质 + 线性表的实现
一、什么是数据结构将现实世界的数据组织成为一些具有特定关系的逻辑结构,再把这些逻辑结构的数据映射到计算机的物理存储结构中,这便是计算机科学中的数据结构要解决的问题。数据按照一定的关系结构映射到计算机内存中后,需要在内存中处理这些数据结构,如何在内存中操作这些数据结构就是算法要解决的问题了。对同一个现实问题,使用不同的数据结构和算法进行存储和计算,表现出来的效率是不一样的,如何评价这些数据组织与存储结构及其对应的操作方法,这便需要引入时间和空间复杂度这把标尺了。原创 2019-12-18 23:39:47 · 1482 阅读 · 0 评论 -
数据结构与算法分析(六)--- 分治与减治 + 分治排序与二分查找
一、分治算法分治(divide and conquer)的全称为“分而治之”,分治算法主要由两部分构成: - 分(divide):递归求解所有从原问题分解出来的相似子问题; - 治(conquer):从子问题的解构建原问题的解。分治算法将原问题划分成若干个规模较小而结构与原问题相似的子问题,然后递归求解所有子问题,最后合并所有子问题的解,即可得到原问题的解。在函数正文中至少含有两个递归调用的例程叫做分治算法,而函数正文中只含一个递归调用的例程不是分治算法(可以称为减治算法)。原创 2019-12-13 18:53:19 · 2935 阅读 · 0 评论 -
数据结构与算法分析(五)--- 递推与递归 + 减治排序
一、递归与尾递归人有人的思维,计算机有计算机的思维,它们很不相同。如果你要问其中最大的不同是什么,那就是一种被称为递归(recursive)的逆向思维。相比之下,人的正向思维被称为递推(iterative)。要了解什么是递归,我们先了解什么是递推。递归就在于使用计算机自顶向下、从整体到局部的思维方式分析问题,找到把原问题自顶向下层层展开(或分解)的递推公式,通过不断重复使用递推公式,把原问题展开(或分解)到有已知解的递归边界处,再从递归边界的已知解,自底向上递推(或回归)求得原问题的解。原创 2019-12-09 22:37:18 · 2164 阅读 · 0 评论