3 / 6 第一题问题描述
小R正在组织一个比赛,比赛中有 n 支队伍参赛。比赛遵循以下独特的赛制:
- 如果当前队伍数为 偶数,那么每支队伍都会与另一支队伍配对。总共进行
n / 2场比赛,且产生n / 2支队伍进入下一轮。 - 如果当前队伍数为 奇数,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行
(n - 1) / 2场比赛,且产生(n - 1) / 2 + 1支队伍进入下一轮。
小R想知道在比赛中进行的配对次数,直到决出唯一的获胜队伍为止。
测试样例
样例1:
输入:
n = 7
输出:6
样例2:
输入:
n = 14
输出:13
样例3:
输入:
n = 1
输出:0
问题理解
你需要计算在比赛中进行的配对次数,直到决出唯一的获胜队伍为止。比赛规则如下:
- 如果当前队伍数为偶数,每支队伍都会与另一支队伍配对,进行
n / 2场比赛,产生n / 2支队伍进入下一轮。 - 如果当前队伍数为奇数,随机轮空并晋级一支队伍,其余的队伍配对,进行
(n - 1) / 2场比赛,产生(n - 1) / 2 + 1支队伍进入下一轮。
数据结构选择
这个问题不需要复杂的数据结构,只需要一个整数来记录当前的队伍数,并计算配对次数。
算法步骤
- 初始化:初始化一个变量
pair_count来记录配对次数,初始值为0。 - 循环:使用一个循环,直到队伍数
n变为1。- 如果
n是偶数,增加n / 2次配对,并将n更新为n / 2。 - 如果
n是奇数,增加(n - 1) / 2次配对,并将n更新为(n - 1) / 2 + 1。
- 如果
- 返回结果:循环结束后,返回
pair_count。
关键点
- 每次循环中,根据
n的奇偶性更新pair_count和n。 - 循环的条件是
n > 1,因为当n为1时,比赛已经结束。
代码实现
def solution(n: int) -> int:
# write code here
# 初始化配对次数
pair_count = 0
# 循环直到队伍数为1
while n > 1:
if n % 2 == 0:
# 如果队伍数为偶数
pair_count += n // 2 # 增加配对次数
n = n // 2 # 更新队伍数
else:
# 如果队伍数为奇数
pair_count += (n - 1) // 2 # 增加配对次数
n = (n - 1) // 2 + 1 # 更新队伍数
return pair_count
if name == 'main':
print(solution(7) == 6)
print(solution(14) == 13)
print(solution(1) == 0)
3 / 6 第二题问题描述
小R正在研究DNA序列,他需要一个函数来计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括:增加一个碱基、删除一个碱基或替换一个碱基。
测试样例
样例1:
输入:
dna1 = "AGT",dna2 = "AGCT"
输出:1
样例2:
输入:
dna1 = "AACCGGTT",dna2 = "AACCTTGG"
输出:4
样例3:
输入:
dna1 = "ACGT",dna2 = "TGC"
输出:3
样例4:
输入:
dna1 = "A",dna2 = "T"
输出:1
样例5:
输入:
dna1 = "GGGG",dna2 = "TTTT"
输出:4
问题理解
你需要计算将一个受损DNA序列(dna1)转换成一个未受损序列(dna2)所需的最少编辑步骤。编辑步骤包括:增加一个碱基、删除一个碱基或替换一个碱基。
数据结构选择
这个问题可以通过动态规划(Dynamic Programming, DP)来解决。动态规划的核心思想是将问题分解为子问题,并存储子问题的解以避免重复计算。
算法步骤
-
定义状态:
- 使用一个二维数组
dp,其中dp[i][j]表示将dna1的前i个字符转换成dna2的前j个字符所需的最少编辑步骤。
- 使用一个二维数组
-
初始化:
- 当
dna2为空时,将dna1转换为空序列需要删除dna1的所有字符,因此dp[i][0] = i。 - 当
dna1为空时,将空序列转换为dna2需要增加dna2的所有字符,因此dp[0][j] = j。
- 当
-
状态转移:
- 如果
dna1[i-1] == dna2[j-1],则不需要进行任何编辑操作,dp[i][j] = dp[i-1][j-1]。 - 否则,需要考虑三种操作:
- 删除:删除
dna1的第i个字符,dp[i][j] = dp[i-1][j] + 1。 - 增加:在
dna1的第i个字符后增加dna2的第j个字符,dp[i][j] = dp[i][j-1] + 1。 - 替换:将
dna1的第i个字符替换为dna2的第j个字符,dp[i][j] = dp[i-1][j-1] + 1。
- 删除:删除
- 取这三种操作的最小值作为
dp[i][j]的值。
- 如果
-
最终结果:
dp[m][n]即为将dna1转换为dna2所需的最少编辑步骤,其中m和n分别是dna1和dna2的长度。
代码实现
def solution(dna1, dna2):
# Please write your code here
m, n = len(dna1), len(dna2)
# 创建一个 (m+1) x (n+1) 的二维数组 dp
dp = [[0] * (n + 1) for _ in range(m + 1)]
# 初始化 dp 数组
for i in range(m + 1):
dp[i][0] = i
for j in range(n + 1):
dp[0][j] = j
# 填充 dp 数组
for i in range(1, m + 1):
for j in range(1, n + 1):
if dna1[i - 1] == dna2[j - 1]:
dp[i][j] = dp[i - 1][j - 1]
else:
dp[i][j] = min(dp[i - 1][j] + 1, # 删除
dp[i][j - 1] + 1, # 增加
dp[i - 1][j - 1] + 1) # 替换
# 返回最终结果
return dp[m][n]
if name == "main":
# You can add more test cases here
print(solution("AGCTTAGC", "AGCTAGCT") == 2 )
print(solution("AGCCGAGC", "GCTAGCT") == 4)
3/ 6 第三题问题描述
小U手中有两个数字 a 和 b。第一个数字是一个任意的正整数,而第二个数字是一个非负整数。她的任务是将第二个数字 b 插入到第一个数字 a 的某个位置,以形成一个最大的可能数字。
你需要帮助小U找到这个插入位置,输出插入后的最大结果。
测试样例
样例1:
输入:
a = 76543, b = 4
输出:765443
样例2:
输入:
a = 1, b = 0
输出:10
样例3:
输入:
a = 44, b = 5
输出:544
样例4:
输入:
a = 666, b = 6
输出:6666需要一点思路提示
问题理解
你需要将数字 b 插入到数字 a 的某个位置,使得插入后的数字最大。
数据结构选择
- 由于我们需要逐位比较数字,将数字转换为字符串是一个合理的选择。
算法步骤
- 初始化最大结果:将
b插入到a的最前面,作为初始的最大结果。 - 遍历字符串
a:尝试将b插入到a的每一位后面,生成新的数字。 - 比较并更新最大结果:每次生成新的数字后,与当前的最大结果进行比较,如果新的数字更大,则更新最大结果。
- 返回最大结果:遍历结束后,返回最大结果。
关键点
- 将数字转换为字符串后,可以通过字符串的切片操作来插入
b。 - 每次插入后,需要将字符串转换回整数进行比较。
代码实现
def solution(a: int, b: int) -> int:
# write code here
# 将数字 a 转换为字符串,以便我们可以逐位比较
str_a = str(a)
str_b = str(b)
# 初始化最大结果为将 b 插入到 a 的最前面
max_result = int(str_b + str_a)
# 遍历字符串 a 的每一位,尝试将 b 插入到每一位后面
for i in range(len(str_a) + 1):
# 构造新的数字
new_number = int(str_a[:i] + str_b + str_a[i:])
# 更新最大结果
if new_number > max_result:
max_result = new_number
return max_result
if name == 'main':
print(solution(76543, 4) == 765443)
print(solution(1, 0) == 10)
print(solution(44, 5) == 544)
print(solution(666, 6) == 6666)