引言
随着AI领域的发展,底层算法确实起到了决定性的作用。为了跟上这个快速发展的领域,我们需要不断学习和提升自己的技能。刷题是一种很好的方式,可以帮助我们巩固基础知识,提高解决问题的能力。
介绍
豆包青训营是由字节跳动和稀土掘金社区共同发起的技术培训和人才选拔项目。该项目的目标是培养具有职业竞争力的优秀开发工程师,并提供全程免费的课程,不收取任何费用。
课程内容和方向
豆包青训营的课程涵盖前端、后端和AI方向。在这个飞速发展的AI时代,学员将与豆包MarsCode团队一起深入探索技术领域,学习和运用AI,提高编程效率。此外,课程还包括大数据方向,适合对大数据感兴趣的学员学习,
本文提供训练营试题解析供参考
试题1:负二进制表示问题
问题描述:
小U最近了解到负二进制(base -2)的表示方法。现在给定一个整数 n,小U希望将该整数以负二进制的形式表示,并返回其对应的二进制字符串。注意,除非结果是 “0”,否则返回的字符串中不能包含前导零。
负二进制是一种非标准的进制表示,使用基数 -2 而非通常的 2。在负二进制中,数位的权值是按 (-2)^i 来计算的。
def solution(n: int) -> str:
if n == 0:
return '0'
result = []
while n != 0:
# 计算当前位的余数
remainder = n % -2
n = n // -2
# 处理余数为负的情况
if remainder < 0:
remainder += 2
n += 1
# 将余数添加到结果列表中
result.append(str(remainder))
# 结果列表是反向的,需要反转
result.reverse()
# 将列表转换为字符串并返回
return ''.join(result)
if __name__ == '__main__':
print(solution(n=2) == '110')
print(solution(n=3) == '111')
print(solution(n=0) == '0')
试题2:量化数字的统计
问题描述:
小M最近对一种特别的数字产生了兴趣。他称某个数字为“量化数字”,当且仅当这个数字满足以下两个条件:
1.该数字能被3整除。
2.该数字的所有位数都是相同的数字。
例如,数字666是一个量化数字,因为它能被3整除,并且所有位数都是6。
现在给定两个整数L和R,你需要统计在L到R范围内(包括L和R)的所有量化数字,并返回这个数字的个数。
def solution(L: int, R: int) -> int:
# 初始化计数器
count = 0
# 遍历所有可能的数字位数(1位数,2位数,3位数,...)
for digit in range(1, 10): # 1到9
num = digit
while num <= R:
# 检查当前数字是否在范围内,并且是否能被3整除
if num >= L and num % 3 == 0:
count += 1
# 生成下一个相同数字组成的数字
num = num * 10 + digit
return count
if __name__ == '__main__':
print(solution(L = 5, R = 125) == 6)
print(solution(L = 10, R = 300) == 5)
print(solution(L = 100, R = 999) == 9)
试题3:雇主招聘问题
问题描述:
小U作为一位雇主,想要招聘一位工人。现有 n 个人前来应聘,每个人都写下了他们期望的薪资。小U打算选择期望薪资最低的人,但为了避免纠纷,他只会选择在没有其他人提出相同期望薪资的情况下期望薪资最低的人。如果没有符合条件的人,他将不录用任何人。
你的任务是帮助小U找到合适的最低薪资。如果没有合适的人,输出 -1。
def solution(n: int, salaries: list) -> int:
# 对薪资列表进行排序
sorted_salaries = sorted(salaries)
# 遍历排序后的薪资列表
for salary in sorted_salaries:
# 检查当前薪资是否唯一
if sorted_salaries.count(salary) == 1:
return salary
# 如果没有找到唯一的最低薪资,返回 -1
return -1
if __name__ == '__main__':
print(solution(n = 3, salaries = [3, 2, 1]) == 1)
print(solution(n = 6, salaries = [1, 1, 4, 5, 1, 4]) == 5)
print(solution(n = 3, salaries = [4, 4, 4]) == -1)
试题4:比赛的赢家
问题描述:
小M正在玩一个数组比赛游戏,游戏规则如下:每回合游戏都在所有元素互不相同的数组 arr 的前两个元素 arr[0] 和 arr[1] 之间进行。较大的整数将会取得这一回合的胜利并保留在位置 0,而较小的整数则会被移至数组的末尾。比赛继续,直到某个整数连续赢得 k 次,这个整数即为比赛的赢家。
给定一个整数数组 arr 和一个整数 k,请你返回赢得比赛的整数。题目数据保证游戏中一定存在赢家。
def solution(arr: list, k: int) -> int:
# 初始化当前赢家和连续赢得的回合数
current_winner = arr[0]
win_count = 0
# 模拟比赛过程
while win_count < k:
# 比较前两个元素
if arr[0] > arr[1]:
winner = arr[0]
loser = arr[1]
else:
winner = arr[1]
loser = arr[0]
# 更新当前赢家和计数器
if winner == current_winner:
win_count += 1
else:
current_winner = winner
win_count = 1
# 将较小的元素移到数组末尾
arr.remove(loser)
arr.append(loser)
# 返回当前赢家
return current_winner
if __name__ == '__main__':
print(solution(arr=[2, 1, 3, 5, 4, 6, 7, 9], k=2) == 5)
print(solution(arr=[3, 2, 1, 4], k=10) == 4)
print(solution(arr=[1, 9, 8, 7, 6, 5, 4, 3, 2, 11], k=7) == 9)
试题5:最大UCC子串计算
问题描述:
def solution(m: int, s: str) -> int:
# write code here
n = len(s)
dp = [[-1] * (m + 1) for _ in range(n + 1)] # dp[i][e]:前i个字符编辑e次得到的’UCC'子串数量
dp[0][0] = 0
# 第一次动态规划
# 计算从每个字符开始,为了匹配 "UCC" 产生的最小编辑距离和匹配成功时的长度
# 每个字符的计算过程都是dp
match_info = [[] for _ in range(n)] # match_info[i] = 从s[i]开始,匹配“UCC”的(最小编辑距离,匹配成功时的长度)
for i in range(n):
max_len = min(n - i, 3 + m) # 从当前字符s[i]开始,匹配成功时可能达到的最大长度
# 从当前字符s[i]开始,匹配 "UCC" 的最小编辑距离
dp_match = [[float('inf')] * (max_len + 1) for _ in range(4)]
dp_match[0][0] = 0
for p in range(4): # 从s[i]开始匹配"UCC" 的进度:‘’->‘U'->'UC'->'UCC’
for q in range(max_len + 1): # 匹配过程中划过的长度 = 0,1,...,max_len
if dp_match[p][q] > m: # 编辑次数用完了
continue
if p < 3 and q < max_len: # 保留/替换
cost = 0 if s[i + q] == 'UCC'[p] else 1
dp_match[p + 1][q + 1] = min(dp_match[p + 1][q + 1], dp_match[p][q] + cost)
if p < 3: # 插入
dp_match[p + 1][q] = min(dp_match[p + 1][q], dp_match[p][q] + 1)
if q < max_len: # 删除
dp_match[p][q + 1] = min(dp_match[p][q + 1], dp_match[p][q] + 1)
# 统计
for q in range(max_len + 1):
c = dp_match[3][q]
match_info[i].append((c, q)) # (编辑距离,匹配长度)
# 主过程的动态规划:
for i in range(n + 1):
for e in range(m + 1):
if dp[i][e] == -1:
continue
if i < n: # 不尝试匹配 "UCC" --> 直接跳过/删除当前字符
dp[i + 1][e] = max(dp[i + 1][e], dp[i][e]) # 保留
if e + 1 <= m: # 删除
dp[i + 1][e + 1] = max(dp[i + 1][e + 1], dp[i][e])
if i < n and match_info[i]: # 尝试匹配
for c, l in match_info[i]: # 从当前字符串开始匹配‘UCC’的(最小编辑距离,匹配成功时长度)
if e + c <= m and i + l <= n:
dp[i + l][e + c] = max(dp[i + l][e + c], dp[i][e] + 1)
# 找到最大匹配数量
max_substrings = 0
for e in range(m + 1):
max_substrings = max(max_substrings, dp[n][e])
return max_substrings