青训营-豆包MarsCode技术训练营试题解析十七

介绍

‌豆包青训营‌是由字节跳动和稀土掘金社区共同发起的技术培训和人才选拔项目,主要面向在校大学生。该项目的目标是培养具有职业竞争力的优秀开发工程师,并提供全程免费的课程,不收取任何费用‌。

课程内容和方向

豆包青训营的课程涵盖前端、后端和AI方向。在这个飞速发展的AI时代,学员将与豆包MarsCode团队一起深入探索技术领域,学习和运用AI,提高编程效率‌。此外,课程还包括大数据方向,适合对大数据感兴趣的学员学习‌,

本文提供训练营试题解析供参考

试题1:小M的蛋糕切割问题

问题描述:
小M有一个 n×m的矩形蛋糕,蛋糕被分为 n×m 个区域,每个区域都有一个美味度。她希望通过一刀将蛋糕切成两部分,一部分自己吃,另一部分给小团。切下的区域必须是完整的,即不能把某个小正方形切成两个小区域
小M希望两个人吃的部分的美味度之和尽量接近。你的任务是计算出美味度差的最小值,即
∣s1−s2∣的最小值,其中 s1是小M吃到的美味度,s 2是小团吃到的美味度。

def solution(n: int, m: int, a: list) -> int:
    # 计算二维前缀和数组
    prefix_sum = [[0] * (m + 1) for _ in range(n + 1)]
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            prefix_sum[i][j] = a[i-1][j-1] + prefix_sum[i-1][j] + prefix_sum[i][j-1] - prefix_sum[i-1][j-1]
    
    min_diff = float('inf')
    
    # 遍历所有可能的水平切割线
    for i in range(1, n):
        # 计算上下两部分的美味度之和
        top_sum = get_submatrix_sum(prefix_sum, 0, 0, i, m)
        bottom_sum = get_submatrix_sum(prefix_sum, i, 0, n, m)
        min_diff = min(min_diff, abs(top_sum - bottom_sum))
    
    # 遍历所有可能的垂直切割线
    for j in range(1, m):
        # 计算左右两部分的美味度之和
        left_sum = get_submatrix_sum(prefix_sum, 0, 0, n, j)
        right_sum = get_submatrix_sum(prefix_sum, 0, j, n, m)
        min_diff = min(min_diff, abs(left_sum - right_sum))
    
    return min_diff

# 辅助函数:计算子矩阵的美味度之和
def get_submatrix_sum(prefix_sum, x1, y1, x2, y2):
    return (prefix_sum[x2][y2] 
            - prefix_sum[x1][y2] 
            - prefix_sum[x2][y1] 
            + prefix_sum[x1][y1])

if __name__ == '__main__':
    print(solution(2, 3, [[1, 1, 4], [5, 1, 4]]) == 0)
    print(solution(3, 3, [[3, 2, 1], [4, 5, 6], [7, 8, 9]]) == 3)
    print(solution(2, 2, [[1, 2], [3, 4]]) == 2)

试题2:小M的订单编号问题

问题描述:
商家使用了循环订单编号系统,每次发起订单时,编号会递增,但当编号超过设置的上限
m 时,编号会从 1 重新开始编号。小M想知道,当编号上限为m 时,第 x 个订单的编号是多少。

你需要处理多个查询,每个查询给定 m 和 x,输出第 x 个订单的编号。

def solution(m: int, x: int) -> int:
    # 使用取模运算计算第 x 个订单的编号
    # (x - 1) % m 计算出在循环中的位置,然后 + 1 转换为编号
    return (x - 1) % m + 1

if __name__ == '__main__':
    print(solution(2, 3) == 1)  # 测试样例1
    print(solution(5, 17) == 2)  # 测试样例2
    print(solution(8, 2) == 2)  # 测试样例3
    print(solution(4, 4) == 4)  # 测试样例4

试题3:小R和小S的金币分配问题

问题描述:
小R和小S在探险过程中发现了一个装满金币的宝箱。宝箱里有N枚金币,他们决定按照以下规则来分配:

1.小R和小S轮流选取金币,且小R先选。
2.如果当前剩余的金币数量为偶数时,可以选择拿走一半的金币,或者只拿走一枚金币。
3.如果当前剩余的金币数量为奇数时,只能拿走一枚金币。
两人都会采取最优策略来获取更多的金币。现在,你需要计算小R和小S最终各自拿走的金币数量。

def solution(N: int) -> list:
    def take_coins(N, is_R_turn):
        # 终止条件
        if N == 0:
            return [0, 0]
        
        # 选择策略
        if N % 2 == 1:
            # 奇数情况
            result = take_coins(N - 1, not is_R_turn)
            if is_R_turn:
                result[0] += 1
            else:
                result[1] += 1
            return result
        else:
            # 偶数情况
            # 选择拿走一枚金币
            result1 = take_coins(N - 1, not is_R_turn)
            if is_R_turn:
                result1[0] += 1
            else:
                result1[1] += 1
            
            # 选择拿走一半金币
            result2 = take_coins(N // 2, not is_R_turn)
            if is_R_turn:
                result2[0] += N // 2
            else:
                result2[1] += N // 2
            
            # 选择最优策略
            if is_R_turn:
                return result1 if result1[0] > result2[0] else result2
            else:
                return result1 if result1[1] > result2[1] else result2
    
    # 调用递归函数
    return take_coins(N, True)

if __name__ == '__main__':
    print(solution(1) == [1, 0])
    print(solution(2) == [1, 1])
    print(solution(5) == [2, 3])
    print(solution(6) == [4, 2])

试题4:小R的三倍数分解挑战

问题描述:
小R拿到了一些正整数,这些正整数都是3的倍数。他需要将每一个数n分解为三个3的倍数,并且每种分解方法的顺序不同也视为不同的分解方式。你的任务是帮助小R计算每个n可以分解成三个3的倍数的方法数。如果某个数无法分解,则返回0。需要注意的是,分解出的每个数都不能为0。

def solution(n: int) -> int:
    count = 0
    # 遍历所有可能的组合
    for i in range(3, n + 1, 3):  # i 是第一个3的倍数
        for j in range(3, n + 1, 3):  # j 是第二个3的倍数
            k = n - i - j  # k 是第三个3的倍数
            if k > 0 and k % 3 == 0:
                count += 1
    return count

if __name__ == '__main__':
    print(solution(9) == 1)
    print(solution(12) == 3)

试题5:小R的蛋糕分享

问题描述:
小R手里有一个大小为 n 行 m 列的矩形蛋糕,每个小正方形区域都有一个代表美味度的整数。小R打算切割出一个正方形的小蛋糕给自己,而剩下的部分将给小S。她希望两人吃的部分的美味度之和尽量接近。

我们定义小R吃到的部分的美味度之和为 s_1,而小S吃到的部分的美味度之和为 s_2,请你帮助小R找到一个切割方案,使得 |s_1 - s_2| 的值最小。

def solution(n: int, m: int, a: list) -> int:
    # 创建前缀和矩阵
    prefix_sum = [[0] * (m + 1) for _ in range(n + 1)]
    
    # 计算前缀和矩阵
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            prefix_sum[i][j] = a[i-1][j-1] + prefix_sum[i-1][j] + prefix_sum[i][j-1] - prefix_sum[i-1][j-1]
    
    min_diff = float('inf')
    
    # 遍历所有可能的正方形区域
    for size in range(1, min(n, m) + 1):
        for i in range(size, n + 1):
            for j in range(size, m + 1):
                # 计算正方形区域的美味度之和
                s1 = prefix_sum[i][j] - prefix_sum[i-size][j] - prefix_sum[i][j-size] + prefix_sum[i-size][j-size]
                # 计算剩余部分的美味度之和
                s2 = prefix_sum[n][m] - s1
                # 更新最小差值
                min_diff = min(min_diff, abs(s1 - s2))
    
    return min_diff

if __name__ == '__main__':
    print(solution(3, 3, [[1, 2, 3], [2, 3, 4], [3, 2, 1]]) == 1)
    print(solution(4, 4, [[1, 2, 3, 4], [4, 3, 2, 1], [1, 2, 3, 4], [4, 3, 2, 1]]) == 2)
    print(solution(2, 2, [[5, 5], [5, 5]]) == 10)

试题6:小U数数

问题描述:
小U正在数偶数,从 0,2,4,6,8,10,12,… 开始,依次将这些数连在一起,形成一个无穷长的字符串,例如:“0246810121416…”。小U想知道这个字符串中的第 n 个字符是什么。

def solution(n: int) -> int:
    # 初始化一个空字符串来存储偶数序列
    even_string = ""
    
    # 初始化一个变量来生成偶数
    num = 0
    
    # 循环生成偶数并拼接字符串,直到字符串长度足够长
    while len(even_string) < n:
        # 将当前偶数转换为字符串并拼接到 even_string
        even_string += str(num)
        # 生成下一个偶数
        num += 2
    
    # 返回第 n 个字符
    return int(even_string[n-1])

if __name__ == '__main__':
    print(solution(6) == 1)
    print(solution(10) == 1)
    print(solution(15) == 8)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HappyAcmen

非常感谢大佬的鼓励!感谢感谢!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值