算法实现之动态规划算法实现2

最优二叉搜索树

通过枚举不同的起始位置确定子树的范围,从小到大逐步扩展子树的范围,然后根据根节点的位置,计算当前根节点的总代价。计算总代价的方式是:将子树范围内的键的频率求和,加上左子树和右子树的总代价。左子树的范围是 [i, k-1],右子树的范围是 [k+1, j],其中 k 表示当前根节点的位置。最后通过比较当前总代价和已经计算的最小代价来更新最优解。

python实现:

def optimal_bst(keys, freq):
    n = len(keys)
    dp = [[0] * n for _ in range(n)]    
    # 初始化对角线上的值,即单个节点的情况
    for i in range(n):
        dp[i][i] = freq[i]
    
    # 枚举不同的子树规模
    for subsize in range(2, n+1):
        # 枚举不同的子树起始位置
        for i in range(n - subsize + 1):
            j = i + subsize - 1
            dp[i][j] = float('inf')
            
            # 枚举根节点的位置
            for k in range(i, j + 1):
                # 计算当前根节点的总代价
                cost = sum(freq[i:j+1]) + (dp[i][k-1] if k > i else 0) + (dp[k+1][j] if k < j else 0)
                
                # 更新最优解
                if cost < dp[i][j]:
                    dp[i][j] = cost
    
    return dp[0][n-1]

字符串之间的比对与最优转化路径

通过比较字符的相等与否计算最优值。如果两个字符相等,那么最优值与上一个位置的最优值相等;如果两个字符不相等,那么最优值为上一个位置的最优值、左边位置的最优值和左上角位置的最优值中的最小值加1。

python实现:

def string_comparison(source, target):
    m, n = len(source), len(target)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(m + 1):
        dp[i][0] = i
    for j in range(n + 1):
        dp[0][j] = j
    # 根据字符的相等与否计算最优值
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if source[i - 1] == target[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = min(dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]) + 1
    # 返回最优值
    return dp[m][n]

def string_conversion(source, target):
    m, n = len(source), len(target)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(m + 1):
        dp[i][0] = i
    for j in range(n + 1):
        dp[0][j] = j
    # 根据字符的相等与否计算最优转化路径
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if source[i - 1] == target[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = min(dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]) + 1
    # 构造最优转化路径
    path = []
    i, j = m, n
    while i > 0 and j > 0:
        if source[i - 1] == target[j - 1]:
            path.append('Equal')
            i -= 1
            j -= 1
        else:
            if dp[i][j] == dp[i - 1][j - 1] + 1:
                path.append('Replace')
                i -= 1
                j -= 1
            elif dp[i][j] == dp[i][j - 1] + 1:
                path.append('Insert')
                j -= 1
            else:
                path.append('Delete')
                i -= 1
    # 处理剩余的字符
    while i > 0:
        path.append('Delete')
        i -= 1
    while j > 0:
        path.append('Insert')
        j -= 1
    # 反转路径列表
    path.reverse()
    return path

最大子序列和

不断比较将一元素加入当前子段前和后的结果,实现动态规划。

python实现:

def max_subarray_sum(nums):
    max_sum = current_sum = nums[0]
    for i in range(1, len(nums)):
        current_sum = max(nums[i], current_sum + nums[i])
        max_sum = max(max_sum, current_sum)
    return max_sum

RNA最优二级结构长度

相当于求解最长增长子序列问题。遍历所有可能的起始位置与结束位置,并对配对情况进行检查。

python实现:

def rna_secondary_structure(sequence):
    n = len(sequence)
    dp = [[0] * n for _ in range(n)]

    for length in range(1, n):
        for i in range(n - length):
            j = i + length
            if (sequence[i] == "A" and sequence[j] == "U") or \
               (sequence[i] == "U" and sequence[j] == "A") or \
               (sequence[i] == "C" and sequence[j] == "G") or \
               (sequence[i] == "G" and sequence[j] == "C"):
                dp[i][j] = dp[i+1][j-1] + 1
            else:
                dp[i][j] = max(dp[i+1][j], dp[i][j-1])

    return dp[0][n-1]

本文仅为学习记录,如有错误欢迎指出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值