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

介绍

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

课程内容和方向

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

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

试题1:饭馆菜品选择问题

问题描述:
在这里插入图片描述

def solution(s: str, a: list, m: int, k: int) -> int:
    # 1. 数据预处理:将价格和蘑菇信息结合起来
    dishes = [(a[i], s[i] == '1') for i in range(len(s))]
    
    # 2. 根据价格排序
    dishes.sort(key=lambda x: x[0])
    
    # 3. 选择菜品
    total_price = 0
    mushroom_count = 0
    selected_count = 0
    
    for price, has_mushroom in dishes:
        if selected_count == k:
            break
        if has_mushroom and mushroom_count < m:
            # 选择含有蘑菇的菜
            total_price += price
            mushroom_count += 1
            selected_count += 1
        elif not has_mushroom:
            # 选择不含蘑菇的菜
            total_price += price
            selected_count += 1
    
    # 检查是否选择了足够的菜品
    if selected_count < k:
        return -1
    
    return total_price

if __name__ == '__main__':
    print(solution("001", [10, 20, 30], 1, 2) == 30)
    print(solution("111", [10, 20, 30], 1, 2) == -1)
    print(solution("0101", [5, 15, 10, 20], 2, 3) == 30)

试题2:最小替换子串长度

问题描述:

小F得到了一个特殊的字符串,这个字符串只包含字符A、S、D、F,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得A、S、D、F这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。

def solution(input):
    # 统计字符频次
    from collections import Counter
    count = Counter(input)
    
    # 计算目标频次
    target_count = len(input) // 4
    
    # 计算需要替换的字符
    need_replace = {}
    for char in 'ASDF':
        if count[char] > target_count:
            need_replace[char] = count[char] - target_count
    
    # 如果没有需要替换的字符,直接返回0
    if not need_replace:
        return 0
    
    # 滑动窗口
    left = 0
    min_length = len(input)
    window_count = Counter()
    
    for right in range(len(input)):
        # 更新窗口内的字符频次
        window_count[input[right]] += 1
        
        # 检查窗口是否满足替换条件
        while all(window_count[char] >= need_replace.get(char, 0) for char in 'ASDF'):
            # 更新最小长度
            min_length = min(min_length, right - left + 1)
            
            # 移动左指针
            window_count[input[left]] -= 1
            left += 1
    
    return min_length

if __name__ == "__main__":
    #  You can add more test cases here
    print(solution("ADDF") == 1)
    print(solution("ASAFASAFADDD") == 3)

试题3:和的逆运算问题

问题描述:
n 个整数两两相加可以得到 n(n - 1) / 2 个和。我们的目标是:根据这些和找出原来的 n 个整数。

按非降序排序返回这 n 个数,如果无解,输出 “Impossible”。

import itertools
 
def solution(n, sums):
 
    # 枚举 sums 的所有排列
    for perm in itertools.permutations(sums):
        # 利用 sums 中前面3个值推导出 x1
        # perm[0] 是 x1 + x2, perm[1] 是 x1 + x3, perm[n-1] 是 x2 + x3
        x1 = (perm[0] + perm[1] - perm[n-1]) // 2
 
        # 利用 x1 来推导其他的 xi
        x = [x1]
        for i in range(n-1):
            xi = perm[i] - x1
            x.append(xi)
 
        # 验证 xi 和 xj 是否满足所有 sums 条件
        index = 0
        valid = True
        for i in range(n):
            for j in range(i+1, n):
                if x[i] + x[j] != perm[index]:
                    valid = False
                    break
                index += 1
            if not valid:
                break
 
        # 如果验证通过,返回结果
        if valid:
            return " ".join(map(str, sorted(x)))
 
    # 如果所有排列都不满足,返回 "Impossible"
    return "Impossible"
 
# 测试用例
if __name__ == "__main__":
    print(solution(3, [1269, 1160, 1663]) == "383 777 886")
    print(solution(3, [1, 1, 1]) == "Impossible")
    print(solution(5, [226, 223, 225, 224, 227, 229, 228, 226, 225, 227]) == "111 112 113 114 115")
    print(solution(5, [-1, 0, -1, -2, 1, 0, -1, 1, 0, -1]) == "-1 -1 0 0 1")
    print(solution(5, [79950, 79936, 79942, 79962, 79954, 79972, 79960, 79968, 79924, 79932]) == "39953 39971 39979 39983 39989")

试题4:简单四则运算解析器

问题描述:
小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+、-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。

def solution(expression):
    # 定义运算符优先级
    precedence = {'+': 1, '-': 1, '*': 2, '/': 2}
    
    # 定义两个栈:一个用于存储数字,一个用于存储运算符
    num_stack = []
    op_stack = []
    
    # 用于存储当前的数字
    num = 0
    i = 0
    
    while i < len(expression):
        char = expression[i]
        
        if char.isdigit():
            # 处理数字
            num = num * 10 + int(char)
        
        elif char in precedence:
            # 处理运算符
            # 将当前数字压入数字栈
            num_stack.append(num)
            num = 0
            
            # 处理运算符栈中的运算符
            while op_stack and precedence[op_stack[-1]] >= precedence[char]:
                # 弹出运算符和两个数字进行计算
                op = op_stack.pop()
                num2 = num_stack.pop()
                num1 = num_stack.pop()
                if op == '+':
                    num_stack.append(num1 + num2)
                elif op == '-':
                    num_stack.append(num1 - num2)
                elif op == '*':
                    num_stack.append(num1 * num2)
                elif op == '/':
                    num_stack.append(num1 // num2)  # 注意:整数除法
            
            # 将当前运算符压入运算符栈
            op_stack.append(char)
        
        elif char == '(':
            # 处理左括号
            op_stack.append(char)
        
        elif char == ')':
            # 处理右括号
            # 将当前数字压入数字栈
            num_stack.append(num)
            num = 0
            
            # 处理括号内的表达式
            while op_stack and op_stack[-1] != '(':
                op = op_stack.pop()
                num2 = num_stack.pop()
                num1 = num_stack.pop()
                if op == '+':
                    num_stack.append(num1 + num2)
                elif op == '-':
                    num_stack.append(num1 - num2)
                elif op == '*':
                    num_stack.append(num1 * num2)
                elif op == '/':
                    num_stack.append(num1 // num2)  # 注意:整数除法
            
            # 弹出左括号
            op_stack.pop()
        
        i += 1
    
    # 处理最后一个数字
    if num != 0:
        num_stack.append(num)
    
    # 处理剩余的运算符
    while op_stack:
        op = op_stack.pop()
        num2 = num_stack.pop()
        num1 = num_stack.pop()
        if op == '+':
            num_stack.append(num1 + num2)
        elif op == '-':
            num_stack.append(num1 - num2)
        elif op == '*':
            num_stack.append(num1 * num2)
        elif op == '/':
            num_stack.append(num1 // num2)  # 注意:整数除法
    
    # 返回最终结果
    return num_stack[0]

if __name__ == "__main__":
    # 你可以添加更多测试用例
    print(solution("1+1") == 2)
    print(solution("3+4*5/(3+2)") == 7)
    print(solution("4+2*5-2/1") == 12)
    print(solution("(1+(4+5+2)-3)+(6+8)") == 23)

试题5:数字翻译成字符串的可能性

问题描述:
小M获得了一个任务,需要将数字翻译成字符串。翻译规则是:0对应"a",1对应"b",依此类推直到25对应"z"。一个数字可能有多种翻译方法。小M需要一个程序来计算一个数字有多少种不同的翻译方法。

例如:数字12258可以翻译成 “bccfi”, “bwfi”, “bczi”, “mcfi” 和 “mzi”,共5种方式。

public class Main {
    public static int solution(int num) {
        // 将数字转换为字符串以便于处理
        String numStr = String.valueOf(num);
        int n = numStr.length();
        
        // dp数组,dp[i]表示前i个字符的翻译方法数
        int[] dp = new int[n + 1];
        
        // 初始化dp[0]为1,表示空字符串有一种翻译方法
        dp[0] = 1;
        
        // 遍历字符串,计算dp数组
        for (int i = 1; i <= n; i++) {
            // 单个字符的翻译方法数
            dp[i] = dp[i - 1];
            
            // 如果当前字符和前一个字符可以组成一个有效的翻译(10到25之间)
            if (i > 1) {
                int twoDigits = Integer.parseInt(numStr.substring(i - 2, i));
                if (twoDigits >= 10 && twoDigits <= 25) {
                    dp[i] += dp[i - 2];
                }
            }
        }
        
        // 返回最终结果
        return dp[n];
    }
 
    public static void main(String[] args) {
        // 测试样例
        System.out.println(solution(12258) == 5);
        System.out.println(solution(1400112) == 6);
        System.out.println(solution(2110101) == 10);
        System.out.println(solution(25) == 2);
        System.out.println(solution(1023) == 4);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HappyAcmen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值