常用算法:问题求解与优化
0. 概述
在面对问题求解或优化(求最优解)需求时,提出解决方案的核心思想是:分解问题规模,直到问题规模小到可以用非常简单、直接的方式来解决为止(此规模,称为问题的基本情况)。
根据分解后得到的基本情况(种类)数量,及从整体(规模)问题到基本情况的演进规律,可分别采用分治、递归(可升级为动态规划,二者适用解决的问题情况相同)和贪心算法来求解问题,如下表所示:
整体问题分解结果 | 适用算法 | 结果情况 |
---|---|---|
整体问题有多个独立的不同基本情况(子问题),且已知所有基本情况的并集就是整体问题本身 | 分治 | 全局最优解 |
整体问题只有一种基本情况,且已知整体问题可分解为更小规模的相同问题(直至基本情况规模) | 递归/动态规划 | 全局最优解 |
整体问题只有一种基本情况,但不知道整体问题向基本情况的演进规律 | 贪心 | 局部最优解 |
1. 分治算法
将问题分为若干更小规模的部分,通过解决每一个小规模部分问题,并将结果汇总得到原问题的解
2. 递归算法
递归是一种解决问题的方法,其精髓在于将问题分解为规模更小的相同问题,持续分解,直到问题规模小到可以用非常简单直接的方式来解决。
递归算法的实现过程为:递归函数“调用自身”,由整体问题减小问题规模向基本结束条件演进,到达基本情况后再逐层返回结果推广出整体规模问题的结果。其程序实现要点是:
- 递归算法必须有一个基本结束条件(最小规模问题的直接解决)
- 递归算法必须能改变状态向基本结束条件演进(减小问题规模)
- 递归算法必须调用自身(解决减小了规模的相同问题)
递归调用的实现过程中,容易出现资源耗尽的错误。这是因为当一个函数被调用的时,系统会把调用时的现场数据压入到系统调用栈每次调用,压入栈的现场数据称为栈帧当函数返回时,要从调用栈的栈顶取得返回地址,恢复现场,弹出栈帧,按地址返回。所以当递归的层数太多时,因系统调用栈容量有限,容易出现资源耗尽的错误。
此时应检查程序中是否忘记设置基本结束条件,导致无限递归或者向基本结束条件演进太慢,使递归层数太多、调用栈溢出。若检查无误,在内存大小允许的情况下,可适当增大Python默认的调用栈容量大小(默认为1000层)。在Python内置的sys模块可以获取和调整最大递归深度,如下图所示:
代码实现:
# 递归 v 1.0
coin_dic = {1: 1, 2: 1, 5: 1, 10: 1
}
#
def MakeChange(coin, dic):if coin in dic:return dic[coin]else: return min([1 + MakeChange(coin-v, dic) for v in dic if coin > v])# test
MakeChange(21, coin_dic, temp)
递归实现时,可通过“memoization(记忆化/函数值缓存)”的技术避免重复计算,提高算法计算效率。
# 递归 v2.0:增加备忘录(memoization)
coin_dic = {1: 1, 2: 1, 5: 1, 10: 1
}
temp = coin_dic.copy()
#
def MakeChange(coin, dic, temp):if coin in temp:return temp[coin]else:temp[coin] = min([1 + MakeChange(coin-v, dic, temp) for v in dic if coin > v])return temp[coin]# test
MakeChange(21, coin_dic, temp)
3. 动态规划
动态规划较递归算法的主要改进是:直接由基本情况(最优子问题)开始逐步迭代,每一步都依靠以前的最优解来得到本步骤的最优解,直到得到答案。这与递归算法相比,省去了由整体问题分解到基本情况的过程,节省了现场数据压入到系统调用栈所需的存储空间,在时间复杂度和空间复杂度上有显著提升。值得注意的是:不是所有动态规划问题都可以简化掉备忘录的中间结果缓存空间,使算法空间复杂度下降到 O(1) 的。(比如下例硬币兑换问题中,就无法简化掉备忘录空间)
示例代码实现:
# 动态规划
coin_dic = {1: 1, 2: 1, 5: 1, 10: 1
}
def dpMakeChange(dic, coin):# 中间结果缓存temp = coin_dic# 规模演进for i in range(1, coin+1, 1):if i not in temp:temp[i] = min([1 + temp.get(i-v, 10*i) for v in dic])return temp[coin]# test
dpMakeChange(coin_dic, 11)
4. 贪心算法
常用算法:问题求解与优化相关推荐
- 数学建模常用算法:启发式优化算法合辑(内含多种智能优化算法,使用java实现算法、详细注释、并进行结果可视化)
一.启发式算法介绍 启发式算法(heuristic algorithm)是相对于最优化算法提出的.一个问题的最优算法求得该问题每个实例的最优解.启发式算法可以这样定义:一个基于直观或经验构造的算法 ...
- 深度学习最常用的学习算法:Adam优化算法
上海站 | 高性能计算之GPU CUDA培训 4月13-15日 三天密集式学习 快速带你晋级 阅读全文 > 正文共6267个字,30张图,预计阅读时间16分钟. 听说你了解深度学习最常用的学习 ...
- 【转】听说你了解深度学习最常用的学习算法:Adam优化算法?
深度学习常常需要大量的时间和机算资源进行训练,这也是困扰深度学习算法开发的重大原因.虽然我们可以采用分布式并行训练加速模型的学习,但所需的计算资源并没有丝毫减少.而唯有需要资源更少.令模型收敛更快的最 ...
- 集体智慧及其常用算法
集体智慧定义 是指由许多的个体通过合作与竞争中所显现出来的智慧,集体智慧是一种共享的或者群体的智能.它是从许多个体的合作与竞争中涌现出来的.集体智慧在细菌.动物.人类以及计算机网络中形成,并以多种形式 ...
- 对比 GA 、PSO 、DE三种算法 求解连续优化问题的性能
摘要: 演化计算又称为进化算法.进化计算,是一种元启发式方法.搜索过程是从一个初始解的集合(称为初始种群)开始的,种群中的每一个解都沿着一定的轨迹搜索,每前进一步称为种群的进化,得到的解集称为种群的一 ...
- 算法设计之五大常用算法设计方法总结
算法设计之五大常用算法设计方法总结 一.[分治法] 在计算机科学中,分治法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再 ...
- 分类问题常用算法之支持向量机SVM
支持向量机 SVM(Support Vector Machines,支持向量机)是核变换技术的代表算法之一,是一种具有精度高.运算速度快.泛化能力强等优点的统计学习新算法,其主要思想是将低维空间中的线 ...
- 数据 + 进化算法 = 数据驱动的进化优化?进化算法 PK 数学优化
数据 + 进化算法 = 数据驱动的进化优化?进化算法 PK 数学优化 https://baijiahao.baidu.com/s?id=1600164518587031730&wfr=spid ...
- 图解:轻松看懂机器学习十大常用算法
源 / 人人宽客 通过本篇文章大家可以对ML的常用算法形成常识性的认识.没有代码,没有复杂的理论推导,仅是图解,介绍这些算法是什么以及如何应用(例子主要是分类问题).以后有机会再对单个算法做深入地解析 ...
- 轻松看懂机器学习十大常用算法
本文转载自CSDN aliceyangxi1987的博客 通过本篇文章可以对机器学习(machine learning, ML)的常用算法有个常识性的认识,没有代码,没有复杂的理论推导,就是图解一下, ...
最新文章
- IOS NSString 操作
- (3)-JSONObject的过滤设置
- win32 api setwindowlong 第2个参数_FME与MapBox 01:等时圈(Isochrone)API
- 《Cloud Native Infrastructure》CHAPTER 7 (1)
- Session.run() Tensor.eval()
- [转载] 必须要会回答的Java面试题(字符串篇)
- qdialog 返回值_c – QDialog exec()并获取结果值
- 【java】Thread.Sleep(0) 与 Thread.onSpinWait
- 音乐计算机官方.,Boom音乐电脑版
- hiho一下 第六十六周
- Spring Boot 使用 Log4j2
- 打印机提示手动进纸解决办法
- (2)Mac安装Parallels无法上网
- ArcMap数据处理
- C语言程序设计的七个准备步骤
- 像中文的罗马音字体复制_帮我把日语的罗马音弄成汉字!
- 【书山有路】互联网+:从IT到DT 读书笔记
- lzg_ad:XPE网络功能组件
- 天使之火Angelfire:CIA入侵Windows系统的恶意软件
- 计算机辅助绘图中测距在哪,cad测距(cad测量距离快捷键)