5 递归 分治 回溯 贪心算法 二分查找 动态规划

关键:寻找重复子问题

递归

#python
def recursion(level, param1,param2,...):
	#recursion terminator
	if level > MAX_LEVEL:
		process_result
		return
	#process logic in current level
	process(level, data...)
	#drill down
	self.recursion(level + 1,p1,...)
	#reverse the current level status if needed
//java
public void recur(int level, int param){
	//terminator
	if(level > MAX_LEVEL){
	//process result
	return;
	}
	//process current logic
	process(level,param);
	//drill down
	recur(level:level+1,newParam);
	//restore current status
	

分治

divide&conquer

#分治代码模板
def divide_conquer(problem,param1,param2,...):
	#recursion terminator
	if problem is None:
		print_result
		return
	#prepare data
	data = prepare_data(problem)
	wubproblems = split_problem(problem,data)
	#conquer subproblems
	subresult1 = self.divide_conquer(subproblems[0],p1,...)
	subresult2=self.divide_conquer(subproblems[1],p1,...)
	subresult3=self.divide_conquer(subproblems[2],p1,...)
	...
	#process and generate the final result
	result = process_result(subresult1,subresult2,subresult3...)
	#revert thr current level states

在这里插入图片描述
在这里插入图片描述

回溯

Backtracking
思想是试错
回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两种情况:

• 找到一个可能存在的正确的答案;

• 在尝试了所有可能的分步方法后宣告该问题没有答案。

在最坏的情况下,回溯法会导致一次复杂度为指数时间的计算。

DFS BFS

结点

#python
class TreeNode:
	def __init__(self,val):
		sef.val = val
		self.left,self.right = None,None
//java
public class TreeNode{
	public int val;
	public TreeNode left,right;
	public TreeNode(int val){
		this.val = val;
		this.left = null;
		this.right = null;
	}
	}
dfs递归
visited = set()
def dfs(node,visited):
	if node in visited:#terminator
		#already visited
		return
	visited.add(node)
	#process current node here
	for next_node in node.children():
		if not next_node in visited:
			dfs(next_node,visited)
	

在这里插入图片描述

dfs非递归
def DFS(self,tree):
	if tree.root id None:
		return []
	visited,stack=[],[tree,root]
	while stack:
		node = stack.pop()
		visited.add(node)
		process(node)
		nodes = generate_related_nodes(node)
		stack.push(nodes)
bfs代码
def bfs(graph ,start,end):
	queue =[]
	queue.append([start])
	visited.add(start)

	while queue:
	node = queue.pop()
	visited.add(node)
	
	process(node)
	nodes = generate_related_nodes(node)
	queue.push(nodes)
	

在这里插入图片描述

贪心算法

Greedy
问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。这种子问题最优解称为最优子结构。

每一步选择重都采取在当前状态下最好的选择。

贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。

动态规划 和 递归或者分治 没有根本上的区别(关键看有无最优的子结构)
拥有共性:找到重复子问题

差异性:最优子结构、中途可以淘汰次优解

二分查找

目标函数单调
存在上下界(bounded)
能够通过索引访问(index accessible)

left ,right = 0,len(array)-1
while left <= right:
	mid = (left +right)/2
	if array[mid] == target:
		#find the target!!
		break or return result
	elif array[mid]<target:
		left = mid+1
	else:
		right = mid -1

在这里插入图片描述
在这里插入图片描述

动态规划

状态转移方程(DP方程)

关键点:

  1. 最优子结构 opt[n] = best_of(opt[n-1], opt[n-2], …)

  2. 储存中间状态:opt[i]

  3. 递推公式(状态转移方程或者 DP 方程)
    Fib: opt[i] = opt[n-1] + opt[n-2]
    二维路径:opt[i,j] = opt[i+1][j] + opt[i][j+1] (且判断a[i,j]是否空地)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
五大常用算法是动态规划分治递归、贪心和回溯动态规划是一种将问题分解成子问题并保存子问题解的方法。通过求解子问题,可以逐步推导出原始问题的解。动态规划通常用于求解最优化问题,例如最长公共子序列、最短路径等。 分治是将原问题划分成多个相互独立的子问题,然后通过递归的方式求解子问题,并将子问题的解合并成原问题的解。分治算法常用于排序、快速幂等问题。 递归是通过函数调用自身来解决问题的方法。递归算法在问题定义可以被分解为较小规模或更简单情况的时候很有用。例如,计算一个数的阶乘,就可以使用递归实现。 贪心算法是一种选择当前最优策略的方法,即在每一步选取最优解,最终得到全局最优解的算法。贪心算法通常用于解决无后效性的问题,例如最小生成树、哈夫曼编码等。 回溯是一种通过穷举搜索所有可能的解空间,找到满足条件的解的方法。回溯算法在解决组合问题、排序问题、子集和问题等方面很有效。回溯算法通过递归的方式逐步构建解,当发现当前解不满足条件时,会回退到上一步继续搜索其他可能的解。 这五种常用算法在不同的问题领域中都有广泛应用,每种算法都有自己的特点和适用范围。在解决具体问题时,可以根据问题的性质和要求选择最适合的算法进行求解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值