【Leetcode】随笔

文章目录

🌈你好呀!我是 山顶风景独好

🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然!😊

🌸愿您在此停留的每一刻,都沐浴在轻松愉悦的氛围中。

📖这里不仅有丰富的知识和趣味横生的内容等您来探索,更是一个自由交流的平台,期待您留下独特的思考与见解。🌟

🚀让我们一起踏上这段探索与成长的旅程,携手挖掘更多可能,共同进步!💪✨

题目一:最大二叉树(LeetCode 654)

题目分析:

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值左边的子数组前缀上构建左子树。
  3. 递归地在最大值右边的子数组后缀上构建右子树。
    返回由给定数组 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等你哦!我的主页😍

相关推荐
百度Geek说39 分钟前
第一!百度智能云领跑视觉大模型赛道
算法
big_eleven1 小时前
轻松掌握数据结构:二叉树
后端·算法·面试
big_eleven1 小时前
轻松掌握数据结构:二叉查找树
后端·算法·面试
CoovallyAIHub1 小时前
农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
深度学习·算法·计算机视觉
执子手 吹散苍茫茫烟波1 小时前
LCR 076. 数组中的第 K 个最大元素
leetcode·排序算法
kyle~2 小时前
OpenCV---特征检测算法(ORB,Oriented FAST and Rotated BRIEF)
人工智能·opencv·算法
初学小刘2 小时前
决策树:机器学习中的强大工具
算法·决策树·机器学习
科大饭桶3 小时前
C++入门自学Day11-- String, Vector, List 复习
c语言·开发语言·数据结构·c++·容器
lxmyzzs4 小时前
【图像算法 - 16】庖丁解牛:基于YOLO12与OpenCV的车辆部件级实例分割实战(附完整代码)
人工智能·深度学习·opencv·算法·yolo·计算机视觉·实例分割