11月14日-11月17日刷题总结 | 豆包MarsCode AI刷题

81 阅读5分钟

11月14日 构造特定数组的逆序拼接

问题描述 

小U得到了一个数字n,他的任务是构造一个特定数组。这个数组的构造规则是:对于每个i从1到n,将数字n到i逆序拼接,直到i等于n为止。最终,输出这个拼接后的数组。 

例如,当n等于3时,拼接后的数组是 [3, 2, 1, 3, 2, 3]。

思考

可以构造一个特定的数组,通过从 1 到 n 的循环,对每个 i 构造从 n 到 i 的逆序部分数组,并拼接到最终结果中。

代码

def solution(n: int) -> list:    
    result = []       
    for i in range(1, n+1, 1):        
        result.extend(range(n, i-1, -1))  
    return result

知识点:

  • range 的逆序用法:range(n, i-1, -1) 会生成从 n 到 i(含 i)的数字序列,步长为 -1。 
  • list.extend:将一个可迭代对象中的元素逐一添加到列表尾部。

感想

本题比较简单,我们通过使用 range 的逆序生成特性,避免了手动构造和翻转数组,简洁高效。

11月15日 饭馆菜品选择问题

问题描述 

小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 i 道菜是否含有蘑菇。如果 s_i = '1',那么第 i 道菜含有蘑菇,否则没有。 小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1。

思考

问题分析: 小C需要在满足 菜品数量 = k 和 蘑菇菜数量 ≤ m 的条件下,找到最小的总价格。 由于蘑菇菜和非蘑菇菜有不同的限制条件,这需要进行分类处理,分别对两类菜进行筛选。 动态规划是解决这个问题的核心工具,适用于这类约束优化问题。 

实现步骤: 

  • 分类处理: 将所有菜品分为 蘑菇菜 和 非蘑菇菜。 分别对两类菜按照价格升序排序。 
  • 动态规划建模: 使用二维数组dp[i][j] ,表示选择了 i 道菜,其中有 j 道是蘑菇菜时的最小总价格。 dp[0][0] = 0 表示没有选菜时价格为 0。 
  • 动态转移: 遍历非蘑菇菜,将它们加入到 dp 中更新价格。 遍历蘑菇菜,限制蘑菇菜数量 j 的上限。 
  • 结果提取: 通过检查 dp[k][j] 中满足 j≤m 的最小值来得到答案。

代码

def solution(s: str, a: list, m: int, k: int) -> int:   # 分类菜品为含有蘑菇的和不含蘑菇的    mushroom_dishes = []    no_mushroom_dishes = []        # 分类操作    for i in range(len(s)):        if s[i] == '1':            mushroom_dishes.append(a[i])        else:            no_mushroom_dishes.append(a[i])    # 对菜品进行价格排序,选择最便宜的    mushroom_dishes.sort()    no_mushroom_dishes.sort()    # 菜品总数    n_mushroom = len(mushroom_dishes)    n_no_mushroom = len(no_mushroom_dishes)    # 如果无法选择k道菜,直接返回-1    if n_mushroom + n_no_mushroom < k:        return -1    # 动态规划数组,dp[i][j]表示选择i道菜并且含有j道蘑菇的最小价格    dp = [[float('inf')] * (m + 1) for _ in range(k + 1)]        # 初始条件    dp[0][0] = 0  # 选择0道菜时,价格是0        # 处理不含蘑菇的菜    for price in no_mushroom_dishes:        for i in range(k, 0, -1):  # 从后往前,防止覆盖之前的结果            for j in range(m + 1):                dp[i][j] = min(dp[i][j], dp[i-1][j] + price)        # 处理含蘑菇的菜    for price in mushroom_dishes:        for i in range(k, 0, -1):            for j in range(1, m + 1):  # j必须大于0,表示要加蘑菇                dp[i][j] = min(dp[i][j], dp[i-1][j-1] + price)        # 找到选择k道菜且蘑菇数量不超过m的最小总价    result = min(dp[k][j] for j in range(m + 1))        return result if result != float('inf') else -1

这道题展示了如何在有限资源和多约束条件下,利用动态规划找到最优解,既是实践算法的良好案例,也是培养优化思维的好机会。这道题虽然解决了特定问题,但方法具有很强的通用性。比如,在解决商品推荐、旅行规划等问题时,可以将动态规划与贪心思想结合。更复杂的场景(如多类菜品的分配)也可以借鉴此方法。

11月16日 比赛配对问题

问题描述 

小R正在组织一个比赛,比赛中有 n 支队伍参赛。比赛遵循以下独特的赛制: 如果当前队伍数为 偶数,那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛,且产生 n / 2 支队伍进入下一轮。

 如果当前队伍数为 奇数,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行 (n - 1) / 2 场比赛,且产生 (n - 1) / 2 + 1 支队伍进入下一轮。 小R想知道在比赛中进行的配对次数,直到决出唯一的获胜队伍为止。

思考

这个问题是模拟一种淘汰赛制,直到剩下唯一的胜利者。每一轮比赛会减少队伍数量,关键在于计算总共进行了多少场比赛。 每场比赛会淘汰一支队伍,因此在总共 n 支队伍中,要决出唯一的胜利者,需要淘汰 n−1 支队伍。因此,比赛的总场次就是 n−1。

代码

def solution(n: int) -> int:    return n-1

本题非常简单,直接通过数学归纳发现淘汰赛的总场次数与队伍数直接相关,问题的复杂性被巧妙简化。 提示我们在处理递归或模拟问题时,可以尝试通过数学规律优化。

11月17日 小F的永久代币卡回本计划

问题描述

小F最近迷上了玩一款游戏,她面前有一个永久代币卡的购买机会。该卡片的价格为 a 勾玉,每天登录游戏可以返还 b 勾玉。小F想知道她至少需要登录多少天,才能让购买的永久代币卡回本。

思考

本题的本质内容是每天返还 b 勾玉的累计收益,何时达到或超过 a 勾玉的购买成本。 可以推导: 小F每天获得 b 勾玉,想知道需要多少天才能回本,即求最小整数 d,满足:d×b≥a 

变形得: 

可以直接使用整除运算和上取整公式。

代码

def solution(a: int, b: int) -> int:    return (a + b - 1) // b

今天打卡的这道题和昨天的一样,都是直观易懂,通过简单公式快速解答,强调了解决问题时的逻辑推导能力。通过发现问题的本质规律,可以大幅提升解决效率,可以避免繁琐的模拟或递归过程。