最优二叉搜索树
通过枚举不同的起始位置确定子树的范围,从小到大逐步扩展子树的范围,然后根据根节点的位置,计算当前根节点的总代价。计算总代价的方式是:将子树范围内的键的频率求和,加上左子树和右子树的总代价。左子树的范围是 [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]
本文仅为学习记录,如有错误欢迎指出。