我们知道计算机中各类应用程序随处可见的,而支撑这些应用程序运行的就是各类数据结构以及各类算法,这就是经典等式程序=数据结构+算法,上一篇幅中我们列举了一些常用的数据结构,那么今天我们来捋一捋日常开发中常见的一些算法思想以及具体算法各自的特性及相关指标
常见算法思想
我们首先介绍下几种常见的算法思想,日常中一些具体的解题算法的思想都依赖于它们,文中列举一些具体算法问题可以自行通过搜索引擎了解
穷举法(Brute Force)
核心思想
顾名思义就是列举出所有可能出现的情况,也称枚举法
特性
- 最简单、最直接、但很暴力的思想(简单粗暴)
- 时间复杂度上也最高(时间耗费高)
- 仅限于数据约束有限的情况(小范围中)
- 能得问题的全部答案(全部解)
适用问题或算法
- 列举100以内所有的素数
- 找出鸡兔同笼问题中所有的鸡和兔的个数
- 找出上海房价在2万-3万的所有房源
分治法(Divide and Conquer)
核心思想
顾名思义分而治之就是该算法的核心思想,递归求解子问题
特性
- 适用于规模大问题求解,将问题拆分成足够小的问题(复杂问题简单化)
- 满足拆分后的小问题和大问题是属于同类情况(处理1条数据和处理n条数据逻辑一样)
- 每个小问题之间不相互依赖(你搞你的,我弄我的)
- 对小问题依次计算后求解后即大问题得到解决(大事化小,小事化了)
- 通常可以通过递归方式来实现分治类的问题(简化代码及逻辑)
适用问题或算法
- 在有序的数列中查找某一个数(二分查找算法)
- 归并排序算法
- 快速排序算法
- 堆排序
贪心算法(Greedy)
核心思想
顾名思义在当前情况下处理问题时都往利益最大化(最优解)的方向考虑
特性
- 可以拆分成多个步骤求解问题(饭要一口一口吃,一口吃不成胖子)
- 求解出每一个步骤中的最优结果及最终的最优结果(利益最大化)
适用问题或算法
- 背包问题(最大价值)
- Dijkstra算法(单源最短路径算法)
- Huffman编码算法(最小生成树算法)
- 理财平台中资产-资金撮合(寻找最合适资产产品和资金人进行交易撮配)
动态规划法(Dynamic Programming)
核心思想
顾名思义就是核心思想就是随机应变,每次遇到问题都会动态调整当前状态,为后续步骤做铺垫
特性
- 将问题拆分成多个子问题(和分治法类似)
- 子问题之间存在依赖关系(下个问题处理依赖于上一个问题的结果)
- 子问题确定后不受后续其他子问题影响(当前做完的事已成定局,后续事项无法影响)
- 分解后会有重复的子问题(记录重复子问题,避免无效计算)
适用问题或算法
- 背包问题(最大重量,最大价值)
- 青蛙上台阶问题
- 两个字符串中最长公共子串问题
回溯法(Backtracking)
核心思想
回溯中文释义为向上推导,当问题从上往下搜索时,发现不满足条件时,尝试原路返回原节点后继续搜索直到找到最终结果(月光宝盒时光倒流)
特性
- 确定问题的结果范围(结果必须存在于一个有限的范围)
- 以深度优先遍历的方式进行搜索
- 基于穷举法思想
适用问题或算法
- 走出迷宫问题
- 八皇后问题
分枝界限法(Branch and Bound)
建设中
关于递归(画外音)
其实在上面几种算法思想中对于具体算法实现时我们都可以通过递归的方式来进行操作,那对于递归我们也可以单独称之为递归算法
初识递归的时候你是否会有这两个感觉:代码原来还可以这么写?思路跟着递归后怎么绕都绕不出来?是的!递归它就是这么神奇!
可能大多数人慢慢对于递归类代码能读的懂,但是对于实际场景进行运用时似乎还是有点无从下手,所以我们先从递归本身出发来看看,我们什么时候可以进行递归处理我们逻辑
线上实际业务场景用到递归场景也很普遍,例如:多级代理商之间的分润处理、裂变推销的个人分享推广业务处理等等
递归函数三部曲
- 问题能否拆分成多个子问题(定位递归函数功能,分而治之)
- 每个子问题的处理逻辑和问题本身处理逻辑是否一致(除了数据范围不一致,100万和1万的区别)
- 是否存在终止条件(死循环可是很可怕的哦)