文章目录
🌈你好呀!我是 山顶风景独好
🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然!😊
🌸愿您在此停留的每一刻,都沐浴在轻松愉悦的氛围中。
📖这里不仅有丰富的知识和趣味横生的内容等您来探索,更是一个自由交流的平台,期待您留下独特的思考与见解。🌟
🚀让我们一起踏上这段探索与成长的旅程,携手挖掘更多可能,共同进步!💪✨
题目一:最大二叉树(LeetCode 654)
题目分析:
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
- 创建一个根节点,其值为 nums 中的最大值。
- 递归地在最大值左边的子数组前缀上构建左子树。
- 递归地在最大值右边的子数组后缀上构建右子树。
返回由给定数组 nums 构建的 最大二叉树 。例如:输入nums = [3,2,1,6,0,5],输出对应最大二叉树(根为6,左子树由[3,2,1]构建,右子树由[0,5]构建)。
解题思路:
递归构建:通过递归找到数组中的最大值作为根节点,再分别对最大值左右两侧的子数组递归构建左右子树。
核心步骤:
- 在当前数组范围中找到最大值的索引和值,创建根节点。
- 递归处理最大值左侧的子数组,作为根节点的左子树。
- 递归处理最大值右侧的子数组,作为根节点的右子树。
终止条件:当数组范围为空(左边界 > 右边界)时,返回null。
示例代码:
python
# 二叉树节点定义
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def constructMaximumBinaryTree(nums):
def build(left, right):
if left > right:
return None
# 找到当前范围内的最大值索引
max_idx = left
for i in range(left, right + 1):
if nums[i] > nums[max_idx]:
max_idx = i
# 创建根节点
root = TreeNode(nums[max_idx])
# 递归构建左右子树
root.left = build(left, max_idx - 1)
root.right = build(max_idx + 1, right)
return root
return build(0, len(nums) - 1)
# 辅助函数:前序遍历验证结果
def preorder(root):
result = []
def dfs(node):
if node:
result.append(node.val)
dfs(node.left)
dfs(node.right)
dfs(root)
return result
# 测试示例
if __name__ == "__main__":
nums = [3,2,1,6,0,5]
root = constructMaximumBinaryTree(nums)
print("最大二叉树的前序遍历:", preorder(root)) # 输出:[6,3,2,1,5,0]
代码解析:
build函数接收数组的左右边界索引,在该范围内构建最大二叉树。
通过遍历找到当前范围的最大值索引,以该值为根节点,左侧子数组构建左子树,右侧子数组构建右子树。
递归终止条件为左边界 > 右边界,此时返回null表示空树。
时间复杂度为O(n²)(最坏情况下数组有序,每次遍历需O(n)时间,递归n层),空间复杂度为O(n)(递归栈深度,最坏为n)。
题目二:任务调度器(LeetCode 621)
题目分析:
给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有 n 个单位时间内 CPU 在执行不同的任务,或者在待命。你需要计算完成所有任务所需要的 最短时间 。例如:输入tasks = ["A","A","A","B","B","B"], n = 2,输出8(执行顺序A→B→待命→A→B→待命→A→B)。
解题思路:
贪心算法:优先安排出现次数最多的任务,减少待命时间。
核心公式:
- 设出现次数最多的任务出现了max_count次,共有max_types个任务出现了max_count次。
- 最少时间为(max_count - 1) × (n + 1) + max_types。
- 若任务总数超过该值,则最少时间为任务总数(此时无需待命)。
逻辑解释:将最多的任务作为框架,每个间隔插入其他任务或待命,最后加上末尾的max_types个任务。
示例代码:
python
from collections import Counter
def leastInterval(tasks, n):
# 统计每个任务的出现次数
task_counts = Counter(tasks)
# 最大出现次数
max_count = max(task_counts.values())
# 出现次数为max_count的任务种类数
max_types = sum(1 for count in task_counts.values() if count == max_count)
# 计算理论最少时间
theory_time = (max_count - 1) * (n + 1) + max_types
# 实际最少时间取理论值和任务总数的最大值
return max(theory_time, len(tasks))
# 测试示例
if __name__ == "__main__":
tasks = ["A","A","A","B","B","B"]
n = 2
print("完成所有任务的最短时间:", leastInterval(tasks, n)) # 输出:8
代码解析:
使用Counter统计每个任务的出现次数,找到最大出现次数max_count和对应的任务种类数max_types。
理论最少时间通过公式计算:(max_count-1)×(n+1)表示除最后一轮外的时间(每个周期n+1个单位),加上max_types表示最后一轮的任务时间。
若任务总数超过理论时间,说明无需待命即可安排所有任务,此时返回任务总数。
时间复杂度为O(m)(m为任务总数,统计次数耗时),空间复杂度为O(1)(最多26种任务,计数器大小固定)。
题目三:零钱兑换(LeetCode 322)
题目分析:
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回-1。你可以认为每种硬币的数量是无限的。例如:输入coins = [1,2,5], amount = 11,输出3(5+5+1=11);输入coins = [2], amount = 3,输出-1。
解题思路:
动态规划:定义dp[i]为凑成金额i所需的最少硬币数,目标是求dp[amount]。
初始化:dp[0] = 0(凑0元需要0个硬币),其他dp[i]初始化为amount + 1(表示不可达)。
状态转移:对于每个金额i(从1到amount),遍历所有硬币面额coin,若coin <= i,则dp[i] = min(dp[i], dp[i - coin] + 1)。
结果判断:若最终dp[amount]仍为amount + 1,则返回-1,否则返回dp[amount]。
示例代码:
python
def coinChange(coins, amount):
# 初始化dp数组,dp[i]表示凑成金额i的最少硬币数
dp = [amount + 1] * (amount + 1)
dp[0] = 0 # base case:0元需要0个硬币
for i in range(1, amount + 1):
# 遍历所有硬币面额
for coin in coins:
# 若硬币面额小于等于当前金额,可尝试使用该硬币
if coin <= i:
# 更新最少硬币数
dp[i] = min(dp[i], dp[i - coin] + 1)
# 若仍为初始值,说明无法凑成该金额
return dp[amount] if dp[amount] <= amount else -1
# 测试示例
if __name__ == "__main__":
coins1, amount1 = [1, 2, 5], 11
print("最少硬币数1:", coinChange(coins1, amount1)) # 输出:3
coins2, amount2 = [2], 3
print("最少硬币数2:", coinChange(coins2, amount2)) # 输出:-1
代码解析:
dp数组的长度为amount + 1,涵盖从0到amount的所有金额,初始值设为amount + 1(大于最大可能的硬币数,即全用1元硬币的情况)。
对于每个金额i,通过遍历所有硬币面额,若硬币可用于凑该金额(coin <= i),则用dp[i - coin] + 1(即凑i - coin金额的硬币数加1个当前硬币)更新dp[i]的最小值。
最终通过判断dp[amount]是否仍为初始值,确定是否能凑成目标金额,返回相应结果。
时间复杂度为O(amount×k)(k为硬币种类数),空间复杂度为O(amount)(dp数组的大小)。
✨ 这就是今天要分享给大家的全部内容了,我们下期再见!😊
🏠 我在CSDN等你哦!我的主页😍