算法题解总结

1 递归

1.1 递归3要素:

  1. 定义函数的功能
  2. 找出递归终止条件
  3. 找出递推关系式

1.2 实例解析

1.2.1 阶乘

第一步定义函数的功能, 定义factorial(n)为求n的阶乘。

def  factorial(n):
	pass

第二步找出递归终止条件, 终止条件就是足够简单的问题, 能直接得出结果的。比如本例中n=1 的时候能直接知道结果是1。

第三步是找出递推关系式, 递推关系式就是从更小的问题能推出当前问题的关系式,比如本例中factorial(n) = n* factorial(n-1)。找递推关系式通常是最复杂的一步。
找到之后我们就可以直接写出完整递归的代码:

def factorial(n):
	if ==1:
		return 1   # 递归终止条件
	return n*factorial(n-1)   # 递推关系式

递归的目的是把一个大的问题拆成更小的子问题,我们只需要知道递归的功能即可,不要把递归一层层拆开来想, 这样很容易形成循环调用而进入死循环。

1.2.2 斐波那契数列

第一步定义函数的功能,,定义fibonacci(n)为斐波那契的第n项。

def fibonacci(n):
	pass

第二步找出递归终止条件,fibonacci(1)=1, fibonacci(2)=1
第三步找出递推关系式 fibonacci(n)=fibonaccio(n-1)+fibonacci(n-2)

def fibonnai(n):
	if n<=2:
		return n    #递归终止条件
	return  fibonacci(n-1) + fibonacci(n-2)

注意: 上面的递归终止条件有2个, 在写递归时, 一个常见的错误就是递归终止条件遗漏导致无限循环。比如,上面的示例中, 如果遗漏了fibonacci(2)=1, 就会计算fibonacci(2)=fibonacci(1)+fibonacci(0),继而会计算fibonacci(0)=fabonacci(-1)+fibonacci(-2), 无限循环下去。丛上面的示例也可以看出, 所谓的递归终止条件, 其实就是最小子问题的解, 是不能通过其他子问题推导出来的, 必须能直接给出。

1.2.3 二叉树的遍历

二叉树的遍历是非常典型的问题, 借助递归实现非常简单。
二叉树的遍历有3种方式, 分别是前序遍历, 中序遍历, 后序遍历, 其中前中后指的都是根节点的访问次序, 因此前序遍历的访问顺序是:根节点->左子树->右子树, 中序遍历的访问顺序是左子树->根节点->右子树, 后序遍历的访问顺序是左子树->右子树->根节点。

前序遍历:
1) 定义函数功能:定义PreOrder(binary_tree)为二叉树的前序遍历;
2)找出递归终止条件:如果根节点为空, 那么遍历结束
3) 找出递推关系式:按照前序遍历的访问次序, 那么接下来应该是PreOrder(left)PreOrder(right)

假设二叉树的结构为:

1
2
3
4
5
6
7
class BinaryTree():
    def __init__(self, root, left, right):
        self.root = root
        self.left = left
        self.right = right


def PreOrder(binary_tree):
    if binary_tree.root is None:
        return
    print(binary_tree.root)
    if binary_tree.left is not None:
        PreOrder(binary_tree.left)
    if binary_tree.right is not None:
        PreOrder(binary_tree.right)


if __name__ == "__main__":
    tree1 = BinaryTree(3, None, None)
    tree2 = BinaryTree(4, None, None)
    tree3 = BinaryTree(2, tree1, tree2)

    tree4 = BinaryTree(6, None, None)
    tree5 = BinaryTree(7, None, None)
    tree6 = BinaryTree(5, tree4, tree5)

    tree7 = BinaryTree(1, tree3, tree6)

    PreOrder(tree7)

遍历结果为:1 2 3 4 5 6 7

同样,可以写出中序遍历如下:

def MidOrder(binary_tree):
    if binary_tree.root is None:
        return
    if binary_tree.left is not None:
        MidOrder(binary_tree.left)
    print(binary_tree.root)
    if binary_tree.right is not None:
        MidOrder(binary_tree.right)

遍历结果为: 3 2 4 1 6 5 7

后序遍历:

def PostOrder(binary_tree):
    if binary_tree.root is None:
        return
    if binary_tree.left is not None:
        PostOrder(binary_tree.left)
    if binary_tree.right is not None:
        PostOrder(binary_tree.right)
    print(binary_tree.root)

遍历结果为: 3 4 2 6 7 5 1

1.2.4 汉诺塔游戏
A、B、C 3根柱子,A柱子上从底部到顶部依次叠着n个从大到小的圆盘,将圆盘从A柱子移动到C柱子,遵循以下规则:
1. 一次只能移动一个圆盘;
2. 小盘必须放在大盘之上;

编写程序输出把圆盘从A移动到C的过程。

还是遵循递归解题的3要素:
1) 定义函数的功能:定义hanoi(A, B, C) 为借助B把A的圆盘移动到C;
2)找出递归终止条件:如果A为空,则递归结束
3) 找出递推关系式:

2.1 动态规划3要素:

  1. 定义数组的含义
  2. 找出数组元素的关系式
  3. 找出初始值

2.2 实例解析

2.2.1 阶乘

第一步定义数组的含义:定义dp[i]为i的阶乘, 这样最终所求的答案就是dp[n]

第二步找出数组元素的关系式 dp[i]=i*dp[i-1]
第三步找出初始条件, dp[1]=1

def facrotial(n):
	dp = [0]*n
	dp[0] =1
	for i in range(1,n):
		dp[i] = i*dp[i-1]
	return dp[n-1]
2.2.2 斐波那契数列

第一步定义数组的含义:定义dp[i]为斐波那契数列的第i项, 那么dp[n]就是最终的答案
第二步找出数组元素的关系式: dp[i]=dp[i-1]+dp[i-2]
第三步找出初始条件: dp[0]=1, dp[1]=1

def fibonacci(n):
	if n<=2:
		return 1
	dp = [0]*n
	dp[0]=1
	dp[1]=1
	for  i in range(2,n):
		dp[i] = dp[i-1]+dp[i-2]
	return dp[n-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值