You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

卡牌取数最大化得分算法验证失败,请求错误排查

卡牌取数问题代码错误分析

问题回顾

桌上排列着一排卡牌,每张卡牌上写有一个自然数。每次操作可从这排卡牌的左端或右端取一张卡牌,总共可进行k次操作。最终得分等于所取卡牌上数字的总和,需确定游戏结束时能获得的最大得分。

你的代码:

def card_counter(arr, k):
    if len(arr) == k:
        return sum(arr)
    rang = len(arr) // 2
    left = arr[:rang]
    right = list(reversed(arr[rang:]))
    c = 0
    for _ in range(k):
        min_arr = left if sum(left) >= sum(
            right) and len(left) > 0 else right
        c += min_arr.pop(0)
    return c


if __name__ == '__main__':
    assert card_counter([1, 2, 3, 4, 5], 5) == 15
    assert card_counter([0, 0, 0], 1) == 0
    assert card_counter([150], 1) == 150

错误原因分析

你的代码能通过自行设计的测试用例,但系统测试失败,核心问题出在策略逻辑完全错误,具体如下:

  • 取数策略不符合最优要求:你把数组硬切成左右两半,每次选当前两半总和较大的区域取数,这种逻辑根本无法覆盖所有最优取数组合。比如测试用例arr=[4,3,2,5], k=3,最优得分是取左2个+右1个(4+3+5=12),但你的代码会取左1个+右2个(4+5+2=11),得到错误结果。
  • 数组分半逻辑无依据:用len(arr)//2分割数组完全是主观臆断,和问题的最优解没有任何关联,直接限制了取数的选择范围,漏掉了很多左端+右端的组合可能。
  • 循环取数逻辑僵化:你对右半区做了反转,每次取pop(0),这种方式只能在固定半区里依次取数,无法灵活调整左端和右端的取数次数,自然得不到最优解。

正确思路与代码

正确的做法是枚举所有可能的取数组合:取i个左端元素,同时取k-i个右端元素(i的范围是0到k,且要保证取数不超过数组长度),计算每种组合的总和,最终取最大值。可以用前缀和来优化计算效率:

def card_counter(arr, k):
    n = len(arr)
    max_sum = 0
    # 前缀和数组,prefix[i]表示前i个元素的累加和
    prefix = [0] * (n + 1)
    for i in range(n):
        prefix[i+1] = prefix[i] + arr[i]
    # 枚举所有左端取i个、右端取k-i个的情况
    for i in range(k + 1):
        right_count = k - i
        # 过滤掉超出数组长度的无效情况
        if i > n or right_count < 0 or right_count > n:
            continue
        # 计算当前组合的总和:左端i个的和 + 右端right_count个的和
        current_sum = prefix[i] + (prefix[n] - prefix[n - right_count])
        if current_sum > max_sum:
            max_sum = current_sum
    return max_sum

这个代码可以正确处理所有场景,包括之前的反例:card_counter([4,3,2,5],3)会返回12,符合最优解。

内容的提问来源于stack exchange,提问作者Cooke09

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 08:38:49