算法常用思想

算法常用思想

递归

1.什么是递归
函数在自身内部调用自己的一种编程技巧叫递归。递归三大要素:

  • 明确函数功能
  • 找出递归结束条件
  • 找出函数等价关系式(递推公式)
    递归总的来说:先递进,后回归。

2.应用条件

  1. 基线条件:函数调用本身,子问题和原始问题求解方法相同,且子问题规模更小。
  2. 递归条件:递归不能是无限的。递归条件避免无限循环。
应用
  • 斐波那契数列
  • 阶乘
  • 二叉树遍历

3.举例
斐波那契数列

def f(x):
    if x <= 2: # 基线条件:结束递归
        return 1
    else:     # 递归条件
        return f(x-1) + f(x-2) # 函数等价关系式
x = int(input("input a intger")) 
n = f(x)
print(n)

小青蛙跳台阶

class Solution(object):
    def numWays(self, n):
        a,b = 1,1
        for _ in range(n):
            a,b = b, a+b
        return a % 1000000007

汉诺塔问题

class Solution:
    def hanota(self, A: List[int], B: List[int], C: List[int]) -> None:
        n = len(A)
        self.move(n, A, B, C)
    # 定义move 函数移动汉诺塔
    def move(self,n, A, B, C):
        if n == 1:
            C.append(A[-1])
            A.pop()
            return 
        else:
            self.move(n-1, A, C, B)  # 将A上面n-1个通过C移到B
            C.append(A[-1])          # 将A最后一个移到C
            A.pop()                  # 这时,A空了
            self.move(n-1,B, A, C)   # 将B上面n-1个通过空的A移到C

作者:z1m
链接:https://leetcode-cn.com/problems/hanota-lcci/solution/tu-jie-yi-nuo-ta-de-gu-shi-ju-shuo-dang-64ge-pan-z/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

5.递归的优缺点
优点:代码简洁,易于理解
缺点:时间空间消耗大,重复计算多,调用栈溢出。
改进:一些数据在递归过程中会重复计算,建立缓存存储这些计算过的数据,减少计算量,这种算法也叫备忘录算法。
链接: https://www.cxyxiaowu.com/7259.html

分治

1 什么是分治
分治:分而治之,即把一个复杂的问题分解成多个相同或相似的子问题,将子问题不断分解直至问题简单到可以直接解出。再将子问题的解合并就可以的到原问题的解。
2 分治步骤
分解——>求解——>合并
分治示意图
3.分治应用
二分查找
归并排序
快速排序
汉诺塔问题

贪心(NP)

1 什么是贪心
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

2 算法流程
1.建立数学模型描述问题
2.将原问题分成若干个子问题
3.找出子问题的最优解
4.把子问题的局部最优解合并成一个解

3.应用
prim最小生成树算法
换酒瓶问题#1518

class Solution(object):
    def numWaterBottles(self, numBottles, numExchange):
        """
        :type numBottles: int
        :type numExchange: int
        :rtype: int
        """
        res = numBottles
        drinked = numBottles
        while res >= numExchange:
            res = res - numExchange
            drinked += 1
            res += 1
        return drinked
动态规划(DP)

1 什么动态规划
动态规划背后的基本思想:大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。动态规划往往用于优化递归问题,例如斐波那契数列,如果运用递归的方式来求解会重复计算很多相同的子问题,利用动态规划的思想可以减少计算量。
一句话解释就是:记住你之前得到的答案。
动态规划三要素:重叠子问题,最优子结构,转移方程。
动态规划的一般问题是最值问题,核心为“穷举”。
动态规划脱离了递归,通常由循环迭代完成计算。

2 算法流程
问题拆解,找到问题之间的联系
状态定义
找出递推方程
实现

回溯

1.什么是回溯:
回溯算法类似枚举的尝试搜索过程。基本思想是:从一条路往前走,能进则进,不进则退回上个路口,换一条路继续走。
回溯问题也是决策树遍历问题。需要思考三个问题:
路径、选择列表、结束条件。

2.回溯算法框架:

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return

    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

3.全排列问题:

def permutation(nums, p, q):
    if p == q:
        s.append(list(nums))
    else:
        for i in range(p, q):
            nums[i], nums[p] = nums[p], nums[i]
            permutation(nums, p + 1, q)
            nums[i], nums[p] = nums[p], nums[i]


s = []
nums = [i for i in range(1, 4)]
permutation(nums, 0, len(nums))
print(s)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值