递归
关键:能不能将原本的问题分解为更小的子问题
- 递归3要素:
1、递归函数的入参和返回值
2、终止条件
3、单层逻辑
回溯
适用于:
- 组合问题:N个数里面按一定规则找出k个数的集合
- 切割问题:一个字符串按一定规则有几种切割方式
- 子集问题:一个N个数的集合里有多少符合条件的子集
- 排列问题:N个数按一定规则全排列,有几种排列方式
- 棋盘问题:N皇后,解数独等等
回溯模板
res=[]
path=[]
def dfs(start,path,num,res):
#start-初始位置,path-搜索路径,num-原数组,res-最终结果
if 结束条件
res.append(path[:])
return
for i in range(len(num)):
path.append(num[i])
dfs(i+1,path,num,res)
path.pop()
深度优先搜索(DFS)
适用于:树或图的遍历
原理:从初始点开始,一直沿着同一个分支遍历,直到该分支结束,然后回溯到上一级继续沿着另一个分支走到底,如此往复,直到所有的节点都有被访问到。
- 二叉树的前序、中序、后序遍历
用到了递归
以前序遍历为例
def traversal(self,root,res):
if root==None:
return;
res.append(root.val)
self.traversal(root.left,res)
self.traversal(root.right,res)
广度优先搜索(BFS)
用到了双头队列deque,先进先出
- 二叉树的层序遍历
关键代码段如下
from collections import deque
que=deque([root])
while que:
size=len(que)
tmp_res=[]
#当前层遍历
for _ in range(size):
cur=que.popleft()
tmp_res.append(cur.val)
if cur.left:
que.append(cur.left)
if cur.right:
que.append(cur.right)
哈希表
适用于:统计频率、快速检验某个元素是否出现过等
原理:根据关键码(key)直接访问值(value)的一种数据结构,只要知道key,可以在O(1)时间内查到value。
动态规划
基本思想:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,当再次遇到时,直接引用答案,不必重新求解。
- 5步骤
1、确定dp数组及下标的含义
2、确定递推公式
3、确定dp数组初始化
4、确定遍历顺序
5、模拟推导dp数组
贪心
思想:先局部最优解,再把这些局部最优解结合后,得到整体最优解。
- 4个步骤
1、将问题分解为若干个子问题
2、找出适合的贪心策略
3、求解每一个子问题的最优解
4、将局部最优解堆叠成全局最优解
分治
“分”: 将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题,子问题继续按照这样划分,直到问题可以被轻易解决.
“治”:将子问题单独进行处理
“合”:将子问题的解进行合并得到原问题的解,因此经常用递归来实现。