问题分析
小R的目标是从字符串的第1个字符走到第n个字符,每走一步会消耗一定的体力值。每次从 s_i 到 s_{i+1} 的消耗是 s_{i+1} - s_i,若差值为负,则小R恢复体力,差值为正,则消耗体力。我们需要判断小R是否能够走到终点,并且如果可以,输出剩余的体力值。
字符转体力值
首先,根据题目中的描述,字符 'a' 代表体力值 1,字符 'b' 代表体力值 2,依此类推。我们可以通过字符的 ASCII 值来进行转换。例如,字符 s[i] 对应的体力值是 ord(s[i]) - ord('a') + 1。
行动策略
- 初始化体力:小R初始时拥有 k 点体力。
- 逐步行走:从
s_1开始,逐步到达s_n,每次从s_i到s_{i+1}时,计算消耗或恢复的体力值。 - 判断是否足够体力:如果体力值在任何一步变成负数,则无法继续走下去。
- 输出结果:如果走到终点,输出剩余体力值;如果中途体力耗尽,输出 -1。
解题步骤
- 读取输入数据,获取字符串
s和初始体力值k。 - 循环遍历字符串中的每一对相邻字符,计算体力变化。
- 判断体力是否足够,若体力不足,提前结束并输出 -1。
- 如果遍历完整个字符串,输出最终剩余的体力值。
def solution(n, k, s):
# 转换每个字符为对应的体力值
def char_to_strength(c):
return ord(c) - ord('a') + 1
# 初始体力
current_strength = k
# 遍历每一对相邻的字符
for i in range(1, n):
# 计算从 s[i-1] 到 s[i] 需要消耗的体力
cost = char_to_strength(s[i]) - char_to_strength(s[i-1])
current_strength -= cost
# 如果体力不足,则返回 -1
if current_strength < 0:
return -1
# 如果走完所有字符,返回剩余的体力值
return current_strength
# 示例测试
print(solution(5, 2, "abcca")) # 输出 2
print(solution(6, 5, "abcdef")) # 输出 0
print(solution(4, 1, "acdb")) # 输出 -1
代码解析
- char_to_strength:这个辅助函数将字符转换为对应的体力值。例如,字符 'a' 转换为 1,'b' 转换为 2,依此类推。
- can_walk:这个函数实现了整体的逻辑。我们初始化体力值为
k,然后从第二个字符开始,计算每一步的体力变化。如果某一步体力变为负数,则返回 -1;如果能走到终点,返回剩余的体力值。
时间复杂度
- 字符串
s的长度为n。 - 每次我们对字符串中的相邻字符进行一次比较和计算,时间复杂度为 O(1)。
- 因此,整个过程的时间复杂度为 O(n)。
测试样例分析
示例 1
输入:
arduino
复制代码
5 2 "abcca"
过程:
- 初始体力为 2。
- 从 'a' 到 'b',消耗
2 - 1 = 1点体力,剩余 1。 - 从 'b' 到 'c',消耗
3 - 2 = 1点体力,剩余 0。 - 从 'c' 到 'c',消耗
3 - 3 = 0点体力,剩余 0。 - 从 'c' 到 'a',恢复
1 - 3 = -2点体力,剩余 2。
输出:
复制代码
2
示例 2
输入:
arduino
复制代码
6 5 "abcdef"
过程:
- 初始体力为 5。
- 从 'a' 到 'b',消耗 1 点,剩余 4。
- 从 'b' 到 'c',消耗 1 点,剩余 3。
- 从 'c' 到 'd',消耗 1 点,剩余 2。
- 从 'd' 到 'e',消耗 1 点,剩余 1。
- 从 'e' 到 'f',消耗 1 点,剩余 0。
输出:
复制代码
0
示例 3
输入:
arduino
复制代码
4 1 "acdb"
过程:
- 初始体力为 1。
- 从 'a' 到 'c',消耗
3 - 1 = 2点体力,剩余 -1。
输出:
diff
复制代码
-1
这道题目要求我们判断小R是否能从字符串的第一个字符走到最后一个字符,并计算剩余的体力值。每次从字符 s_i 到 s_{i+1} 时,消耗或恢复的体力值是 s_{i+1} - s_i。字符 'a' 对应体力值 1,'b' 对应体力值 2,以此类推。初始时小R有 k 点体力,若体力降到负数,小R无法继续走下去。
解决思路是:
- 计算每一步的体力变化。
- 判断小R的体力是否足够走到下一个字符。
- 如果途中体力不足,输出
-1;如果走完全程,输出剩余体力。
每一步的时间复杂度为 O(1),因此整体算法时间复杂度为 O(n),其中 n 是字符串的长度。