题目解析 Day 2 | 豆包MarsCode AI刷题

158 阅读23分钟

17. Base32 编码和解码问题

问题描述

你需要实现一个 Base32 的编码和解码函数。

相比于 Base32,你可能更熟悉 Base64,Base64 是非常常见的用字符串形式表示二进制数据的方式,在邮件附件、Web 中的图片中都有广泛的应用。

Base32 是 Base64 的变种,与 Base64 不同的地方在于 Base64 以 6 bit 为一组作为索引,而 Base32 以 5 bit 为一组作为索引,每一组用一个 ASCII 字符表示。Base 64 总共需要 64 个字符表示,而 Base32 则只需要 32 个字符表示。

Base32 的编码流程如下:

  • 对二进制数据进行预处理:如果二进制数据的 bit 数目不是 5 的倍数的话,在末尾补 0 直至为 5 的倍数。
  • 以 5 bit 为一组进行分组。
  • 将每一组的 5 bit 二进制转换为索引(0 - 31)。
  • 在索引 - 字符转换表中查询索引对应的字符。
  • 根据原始二进制数据的 bit 数目除以 40 后的余数,确定末尾需要补 + 的数目。
  • 如果原始二进制数据 bit 数目除以 40 后的余数是 0 的话,不需要补 +
  • 如果余数是 8,补 6 个 +
  • 如果余数是 16,补 4 个 +
  • 如果余数是 24,补 3 个 +
  • 如果余数是 32,补 1 个 +

Base32 的索引 - 字符转换表如下:

索引:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

字符:9 8 7 6 5 4 3 2 1 0 m n b v c x z a s d f g h j k l p o i u y t

你需要对字符串rawStr进行编码,并对encodedStr进行解码。

解题思路

  1. 定义 Base32 字符表 :首先,我们需要定义 Base32 的字符表,这个表将用于将 5 位二进制数转换为对应的字符。

  2. 编码函数

  • 将输入字符串转换为二进制数据。
  • 对二进制数据进行预处理,确保其长度是 5 的倍数。
  • 将二进制数据按 5 位一组进行分组。
  • 将每组 5 位二进制数转换为对应的 Base32 字符。
  • 根据原始二进制数据的长度,确定末尾需要补 + 的数目。
  1. 解码函数
  • 去除编码字符串末尾的 +
  • 将 Base32 字符转换为对应的 5 位二进制数。
  • 将二进制数据按 8 位一组进行分组。
  • 将每组 8 位二进制数转换为对应的字符。

代码实现

BASE32_CHARS = "9876543210mnbvcxzasdfghjklpoiuyt"

def encode_base32(raw_str):
    # 将字符串转换为二进制数据
    binary_data = ''.join(format(ord(c), '08b') for c in raw_str)
    
    # 预处理:确保二进制数据长度是 5 的倍数
    while len(binary_data) % 5 != 0:
        binary_data += '0'
    
    # 将二进制数据按 5 位一组进行分组
    groups = [binary_data[i:i+5] for i in range(0, len(binary_data), 5)]
    
    # 将每组 5 位二进制数转换为对应的 Base32 字符
    encoded_str = ''.join(BASE32_CHARS[int(group, 2)] for group in groups)
    
    # 根据原始二进制数据的长度,确定末尾需要补 `+` 的数目
    remainder = len(raw_str) * 8 % 40
    if remainder == 8:
        encoded_str += '++++++'
    elif remainder == 16:
        encoded_str += '++++'
    elif remainder == 24:
        encoded_str += '+++'
    elif remainder == 32:
        encoded_str += '+'
    
    return encoded_str
    
def decode_base32(encoded_str):
    # 去除末尾的 `+`
    encoded_str = encoded_str.rstrip('+')
    
    # 将 Base32 字符转换为对应的 5 位二进制数
    binary_data = ''.join(format(BASE32_CHARS.index(c), '05b') for c in encoded_str)
    
    # 将二进制数据按 8 位一组进行分组
    groups = [binary_data[i:i+8] for i in range(0, len(binary_data), 8)]
    
    # 将每组 8 位二进制数转换为对应的字符
    decoded_str = ''.join(chr(int(group, 2)) for group in groups if len(group) == 8)
    
    return decoded_str
    
def decode_multi_part(encoded_str):
    # 使用正则表达式分割多组编码字符串
    parts = re.split(r'\+{1,}', encoded_str)
    
    # 分别解码每一部分,并将结果拼接在一起
    decoded_parts = [decode_base32(part) for part in parts]
    return ''.join(decoded_parts)

def solution(rawStr, encodedStr):
    encoded_result = encode_base32(rawStr)
    decoded_result = decode_multi_part(encodedStr)
    return f"{encoded_result}:{decoded_result}"

18. 打点计数器的区间合并

问题描述

小明正在设计一台打点计数器,该计数器可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。小明需要你帮助他计算,在给定的多组数字范围内,计数器会打多少个点。

例如,给定三个数字范围 [1, 4], [7, 10], 和 [3, 5],计数器首先将这些范围合并,变成 [1, 5][7, 10],然后计算这两个范围内共有多少个唯一数字,即从 1 到 5 有 5 个数字,从 7 到 10 有 4 个数字,共打 9 个点。

解题思路

  1. 排序区间:首先,我们需要对输入的区间进行排序。排序可以基于区间的起始值。

  2. 合并区间:遍历排序后的区间,合并重叠的区间。

  3. 计算唯一数字的数量:合并后的区间将不再有重叠,我们可以直接计算每个区间内的数字数量,并累加得到最终结果。

代码实现

def solution(inputArray):
    # 1. 对区间进行排序,基于区间的起始值
    inputArray.sort(key=lambda x: x[0])
    
    # 2. 合并区间
    merged_intervals = []
    current_start, current_end = inputArray[0]
    
    for start, end in inputArray[1:]:
        if start <= current_end:  # 有重叠
            current_end = max(current_end, end)
        else:  # 没有重叠
            merged_intervals.append([current_start, current_end])
            current_start, current_end = start, end
    
    # 添加最后一个区间
    merged_intervals.append([current_start, current_end])
    
    # 3. 计算唯一数字的数量
    count = 0
    for start, end in merged_intervals:
        count += end - start + 1
    
    return count

19. 多米诺骨牌均衡状态

问题描述

小S玩起了多米诺骨牌,他排列了一行骨牌,并可能将某些骨牌向左或向右推倒。随着骨牌连锁反应的进行,一些骨牌可能因为左右两侧受力平衡而保持竖立。现在小S想要知道在所有动作完成后,哪些骨牌保持竖立。

给定一个表示骨牌初始状态的字符串,其中:

  • "L" 表示该位置的骨牌将向左倒。
  • "R" 表示该位置的骨牌将向右倒。
  • "." 表示该位置的骨牌初始时保持竖立。

模拟整个骨牌倒下的过程,求出最终仍然保持竖立的骨牌的数目和位置。

解题思路

这个问题可以看作是一个模拟问题,我们需要模拟多米诺骨牌倒下的过程,并找出最终保持竖立的骨牌的位置。
模拟倒下过程:
使用一个循环来模拟骨牌倒下的过程,直到没有骨牌的状态发生变化为止。 在每一轮循环中,遍历列表,检查每个竖立的骨牌(".")是否会被其左侧的"R"或右侧的"L"推倒。 如果某个竖立的骨牌会被推倒,则将其状态更新为"R"或"L",并标记状态发生了变化。

代码实现

def solution(num, data):
    while True:  
        new_data = list(data)  # 将字符串转换为列表以便修改  
        changed = False  # 标记是否发生了变化  
          
        # 遍历列表,查找并替换'.'  
        for i in range(num):  
            if new_data[i] == '.':  
                if i > 0 and data[i - 1] == 'R' and (i == num - 1 or data[i + 1] != 'L'):  
                    new_data[i] = 'R'  
                    changed = True  
                if i < num - 1 and data[i + 1] == 'L' and (i == 0 or data[i - 1] != 'R'):  
                    new_data[i] = 'L'  
                    changed = True  
                    # 注意:在Python中,由于我们直接修改了列表,所以不需要担心字符串不可变的问题  
                    # 因此,即使两个if条件都满足,也只会执行最后一个赋值操作(即最后一个if块)  
          
        # 如果没有发生变化,则跳出循环  
        if not changed:  
            break  
          
        # 将列表转换回字符串  
        data = ''.join(new_data)  
      
    # 查找所有'.'的索引  
    indices = [i + 1 for i, char in enumerate(data) if char == '.']  # 索引从1开始计数  
      
    # 构建结果字符串  
    if not indices:  
        return "0"  
      
    result = f"{len(indices)}:" + ','.join(map(str, indices))  
      
    return result

20. 叠盘子排序

问题描述

小M有一个独特的方式来收拾家中的盘子。每次用餐后,他会将盘子按照他们的序号顺序叠放。盘子的序号都是唯一的整数,并且在收拾前就是递增的。小M的叠放规则是,每一堆盘子的序号都是连续递增的,并且至少包含3个盘子。需要编写程序帮助小M确定盘子的叠放方式。

例如,输入的盘子序号是 [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20],按照小M的规则,连续递增序列 -3, -2, -1 可以叠在一起表示为 -3--1,而 18, 19, 20 可以叠在一起表示为 18-20。不满足连续递增至少3个的,如 2, 10, 15, 16 都应单独列出。

解题思路

我们需要将一个整数数组中的元素按照连续递增的规则进行分组,并且每个分组至少包含3个元素。如果一个分组不满足这个条件,则该分组中的每个元素都应单独列出。

算法步骤:

  1. 遍历输入列表:从第一个元素开始遍历,直到最后一个元素。

  2. 检测连续递增序列

    • 记录当前连续递增序列的起始位置。
    • 使用一个内部循环找到连续递增序列的结束位置。
  3. 处理连续序列

    • 如果连续序列的长度大于等于3,则将其作为一个分组添加到结果列表中。
    • 如果连续序列的长度小于3,则将每个元素单独添加到结果列表中。
  4. 构建最终结果字符串:使用 join 方法将结果列表转换为字符串。

代码实现

def solution(plates):
    # 将输入字符串按空格分割成列表,并转换成整数  
    nums = list(map(int, plates.split()))  
      
    # 初始化结果字符串  
    ans = ""  
      
    # 遍历nums列表  
    i = 0  
    while i < len(nums):  
        # 检查是否存在连续递增的三个数字  
        if i + 2 < len(nums) and nums[i] + 1 == nums[i + 1] and nums[i] + 2 == nums[i + 2]:  
            # 找到连续递增序列的结束位置  
            j = i + 3  
            while j < len(nums) and nums[j] == nums[j - 1] + 1:  
                j += 1  
            # 将连续递增序列添加到结果字符串中  
            ans += f"{nums[i]}-{nums[j - 1]},"  
            # 更新i为连续递增序列之后的位置  
            i = j  
        else:  
            # 如果不是连续递增序列,则单独添加数字到结果字符串中  
            ans += f"{nums[i]},"  
            # 移动到下一个数字  
            i += 1  
      
    # 移除结果字符串末尾的逗号  
    return ans[:-1]

21. 分组飞行棋棋子

问题描述

小M和小F在玩飞行棋。游戏结束后,他们需要将桌上的飞行棋棋子分组整理好。现在有 N 个棋子,每个棋子上有一个数字序号。小M的目标是将这些棋子分成 M 组,每组恰好5个,并且组内棋子的序号相同。小M希望知道是否可以按照这种方式对棋子进行分组。

例如,假设棋子序号为 [1, 2, 3, 4, 5],虽然只有5个棋子,但由于序号不同,因此不能形成有效的分组。如果序号是 [1, 1, 1, 1, 1, 2, 2, 2, 2, 2],则可以形成两个有效分组,因此输出为 True

解题思路

  1. 统计每个序号的棋子数量:我们可以使用字典来统计每个序号的棋子数量。
  2. 检查每个序号的棋子数量是否能被5整除:如果所有序号的棋子数量都能被5整除,那么就可以分成有效的分组。

代码实现

def solution(nums):
    # 统计每个序号的棋子数量
    count_dict = {}
    for num in nums:
        if num in count_dict:
            count_dict[num] += 1
        else:
            count_dict[num] = 1
    
    # 检查每个序号的棋子数量是否能被5整除
    for count in count_dict.values():
        if count % 5 != 0:
            return "False"
    
    return "True"

22. 翻转增益的最大子数组和

问题描述

小C面对一个由整数构成的数组,他考虑通过一次操作提升数组的潜力。这个操作允许他选择数组中的任一子数组并将其翻转,目的是在翻转后的数组中找到具有最大和的子数组。小C对这个可能性很感兴趣,并希望知道翻转后的数组中可能得到的最大子数组和是多少。

例如,数组是 1, 2, 3, -1, 4。小C可以选择翻转子数组 -1, 4 得到 1, 2, 3, 4, -1 或者翻转 1, 2, 3, -1 得到 -1, 3, 2, 1, 4,在这两种情况下,最大的子数组和都是 10。

备注:子数组 是数组中的一个连续部分。

解题思路

我们设计一个dp数组,该dp[i]表示以元素i为起点向右的最大子数组和。然后从前往后遍历数组,对于元素i,找到其前面的最大子数组和,假设元素排列为(0...k...j...i...n),且i前面的最大子数组和为sum(k...j),我们翻转k到i-1的子数组,那么这种情况就是包含i的子数组的最优情况,即此时包含i的子数组的和最大。我们通过遍历所有元素求得全局最优解。

代码实现

def solution(N, data_array):
    # 初始化dp数组
    dp = [0] * N
    dp[N - 1] = data_array[N - 1]
    
    # 计算以每个元素为起点的最大子数组和
    for i in range(N - 2, -1, -1):
        dp[i] = data_array[i] + max(0, dp[i + 1])
    
    # 初始化ans和left变量
    ans = dp[0]
    left = data_array[0]
    left_max = max(left, 0)
    
    # 从前向后更新ans和left变量
    for i in range(1, N):
        ans = max(ans, left_max + dp[i])
        left = max(left + data_array[i], data_array[i])
        left_max = max(left_max, left)
    
    return ans

23. 数列差异的最小化

问题描述

小R在研究两个数列之间的关系。他给定了两个数列 a 和 b,长度分别为 n 和 m,并设计了一个有趣的公式:(a[i]b[j])2k2∣(a[i]−b[j])^2−k^2∣,其中 k 是给定的一个整数, 0i<n0j<m 0≤i<n,0≤j<m。现在,小R想知道如何选择数列 a 和 b 中的元素 a[i] 和 b[j],使得这个公式的值达到最小。

给定两个整数数列 a(长度为 n) 和 b(长度为 m),以及一个整数 k,你需要找到这个公式的最小值。

约束条件

  • 1n,m1051n,m1051≤n,m≤1051≤n,m≤105
  • 0k1090k1090≤k≤1090≤k≤109
  • 0a[i],b[j]1090a[i],b[j]1090≤a[i],b[j]≤1090≤a[i],b[j]≤109

解题思路

  • 对数组 a 和 b 进行排序。
  • 使用双指针技术,一个指针遍历 a,另一个指针遍历 b,计算 (a[i]b[j])2k2|(a[i] - b[j])^2 - k^2| 并更新最小值。

代码实现

def solution(n: int, m: int, k: int, a: list[int], b: list[int]) -> int:
    # 对数组 a 和 b 进行排序
    a.sort()
    b.sort()
    
    # 初始化最小值为一个较大的数
    min_diff = float('inf')
    
    # 使用双指针技术遍历数组 a 和 b
    i, j = 0, 0
    while i < n and j < m:
        # 计算当前的公式值
        current_diff = abs((a[i] - b[j])**2 - k**2)
        
        # 更新最小值
        if current_diff < min_diff:
            min_diff = current_diff
        
        # 移动指针以减小当前的差值
        if a[i] > b[j]:
            if a[i] - b[j] > k:
                j += 1
            else :
                i += 1
        else:
            if b[j] - a[i] > k:
                i += 1
            else :
                j += 1
    
    # 处理剩余的元素
    while i < n:
        current_diff = abs((a[i] - b[m-1])**2 - k**2)
        if current_diff < min_diff:
            min_diff = current_diff
        i += 1
    
    while j < m:
        current_diff = abs((a[n-1] - b[j])**2 - k**2)
        if current_diff < min_diff:
            min_diff = current_diff
        j += 1
    
    return min_diff

24. 连续子串和的整除问题

问题描述

小M是一个五年级的小学生,今天他学习了整除的知识,想通过一些练习来巩固自己的理解。他写下了一个长度为 n 的正整数序列 a_0, a_1, ..., a_{n-1},然后想知道有多少个连续子序列的和能够被一个给定的正整数 b 整除。你能帮小M解决这个问题吗?

解题思路

  1. 前缀和:我们可以计算序列的前缀和,即从序列开始到当前位置的和。
  2. 哈希表:我们可以使用哈希表来存储前缀和的余数。如果两个前缀和的余数相同,那么它们之间的子序列的和就是 b 的倍数。

代码实现

def solution(n, b, sequence):
    # 初始化一个哈希表来存储前缀和的余数
    prefix_sum_mod = {0: 1}  # 初始化余数为0的情况
    prefix_sum = 0
    count = 0

    for num in sequence:
        # 计算当前前缀和
        prefix_sum += num
        # 计算当前前缀和的余数
        current_mod = prefix_sum % b

        # 如果哈希表中存在相同的余数,说明存在子序列和为b的倍数
        if current_mod in prefix_sum_mod:
            count += prefix_sum_mod[current_mod]
            prefix_sum_mod[current_mod] += 1
        else:
            prefix_sum_mod[current_mod] = 1

    return count

25. 奇妙货币交易问题

问题描述

小R住在一个名为 X 国的国家,这里的货币非常特殊,面值为 V0,V1,V2,...,VnV^0,V^1,V^2,...,V^n,并且 n 可以无限大。该国的交易规则也很特别:在一次交易中,双方只能对每种面值的货币使用不超过两次。

例如,小R想买一件价格为 198 的物品,货币的基数 V=10 时,小R可以使用 2 张 100(102)100(10^2) 的纸币,卖家则找回 2 张 1(100)(10^0) 的纸币。由于这个奇怪的规则,很多 X 国人都无法快速判断某个物品是否可以用这种方式交易成功,他们常常会请聪明的你来帮助。

你能帮他们判断一下,是否能按照规则用给定的货币面值 V 来完成价格为 W 的交易吗?

解题思路

  • 面值的构成

    • 基于基数 V,可以构成的面值为 V0,V1,V2,...V^0, V^1, V^2, ...
    • 对于每个面值Vi V^i,最多可以使用两次,因此每个面值的贡献可以是 0、ViV^i、或 2×Vi2×V^i
  • 贪心拆分法

    • 为了判断是否可以构成 W,从较大的面值开始拆解。这样,我们能快速确定较高位的贡献。

    • 具体地:

      • 从 W 的最高位开始,将 W 按照 V 进制展开,判断每一位数值是否在允许范围 {0, 1, 2} 内。
      • 如果某一位超过了2并且无法用2张小面值找零,则无法满足规则。
      • 如果某一位为 2 或以下,则可以继续处理下一位。
  • 进位处理

    • 在检查每一位时,如果超过 V,则需要将多余的部分进位到下一位。
    • 重复这一过程,直到我们将所有位都满足规则为止。

代码实现

def solution(V, W):
    if V == 1:
        return "YES"
    carry = 0
     # Continue processing until W reduces to 0
    while W > 0:
        # Get the remainder when dividing by V, which corresponds to the current "digit" in base V
        remainder = W % V
        
        # If the remainder is greater than 2, it's impossible to form W under the given rules
        if remainder > 2:
            if V - remainder > 2 :
                return "NO"
            else :
                carry = 1
        else :
            carry = 0

        # Move to the next "digit" by integer-dividing W by V
        W //= V
    
    # If we processed all digits and never exceeded the allowed count, return True
    return "YES"

26. 小F的永久代币卡回本计划

问题描述

小F最近迷上了玩一款游戏,她面前有一个永久代币卡的购买机会。该卡片的价格为 a 勾玉,每天登录游戏可以返还 b 勾玉。小F想知道她至少需要登录多少天,才能让购买的永久代币卡回本。

解题思路

假设需要n天,那么要保证n×ban \times b \ge a,所以我们使用除法并将最后的结果向上取整。

代码实现

def solution(a: int, b: int) -> int:
    #使用除法并向上取整计算需要的天数
    days = math.ceil(a / b)
    return days

27. 构造特定数组的逆序拼接

问题描述

小U得到了一个数字n,他的任务是构造一个特定数组。这个数组的构造规则是:对于每个i从1到n,将数字n到i逆序拼接,直到i等于n为止。最终,输出这个拼接后的数组。

例如,当n等于3时,拼接后的数组是 [3, 2, 1, 3, 2, 3]

解题思路

我们可以通过构造一个初始的 n 到 1 的列表,然后在每次循环中将列表长度减一,拼接到结果后面。也可以使用双层循环来处理,外层循环控制降序序列的个数,内层循环控制降序序列的范围。

代码实现

def solution(n: int) -> list:
    result = []  # 初始化结果列表
    
    # 初始化一个从n到1的列表
    initial_list = list(range(n, 0, -1))
    
    for i in range(n,0,-1):  # 从0到n-1进行循环
        # 每次将initial_list的前i+1个元素拼接到result中
        result.extend(initial_list[:i])
    
    return result  # 返回结果列表
    
def solution(n: int) -> list:
    result = []  # 初始化结果列表
    
    for i in range(1, n + 1):  # 从1到n进行循环
        # 从n递减到i,将这些数字添加到result中
        for j in range(n, i - 1, -1):
            result.append(j)
    
    return result  # 返回结果列表

28. 比赛配对问题

问题描述

小R正在组织一个比赛,比赛中有 n 支队伍参赛。比赛遵循以下独特的赛制:

  • 如果当前队伍数为 偶数,那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛,且产生 n / 2 支队伍进入下一轮。
  • 如果当前队伍数为 奇数,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行 (n - 1) / 2 场比赛,且产生 (n - 1) / 2 + 1 支队伍进入下一轮。

小R想知道在比赛中进行的配对次数,直到决出唯一的获胜队伍为止。

解题思路

我们可以使用递归的方式来计算总的配对次数。每次配对后,队伍数会减少,直到剩下 1 支队伍。
递归出口:如果 n 为 1,则不需要进行任何配对,直接返回 0。

代码实现

def solution(n: int) -> int:
    # 基本情况:如果只有一支队伍,不需要配对
    if n == 1:
        return 0

    # 递归情况:计算当前轮的配对次数,并加上下一轮的配对次数
    if n & 1 == 0:
        # 偶数队伍
        return n // 2 + solution(n // 2)
    else:
        # 奇数队伍
        return n // 2 + solution(n // 2 + 1)

29. 组成字符串ku的最大次数

问题描述

给定一个字符串 ss,该字符串中只包含英文大小写字母。你需要计算从字符串中最多能组成多少个字符串 "ku"。每次可以随机从字符串中选一个字符,并且选中的字符不能再使用。字符串中的字符大小写可以忽略,即大写和小写字母视为相同。

例如,输入 "AUBTMKAxfuu",从中最多能组成 1 个 "ku"

解题思路

  1. 忽略大小写:我们可以将字符串中的所有字符转换为小写(或大写),这样就可以统一处理。
  2. 统计字符频率:我们需要统计字符 'k' 和 'u' 的出现次数。
  3. 计算最大组合数"ku" 的组合数取决于 'k' 和 'u' 中出现次数较少的那个。

代码实现

def solution(s: str) -> int:
    # 将字符串转换为小写
    s = s.lower()
    
    # 统计字符 'k' 和 'u' 的出现次数
    count_k = s.count('k')
    count_u = s.count('u')
    
    # 计算最多能组成的 "ku" 的数量
    # 返回 count_k 和 count_u 中的较小值
    return min(count_k, count_u)

30. 游戏排名第三大的分数

问题描述

小M想要通过查看往届游戏比赛的排名来确定自己比赛的目标分数。他希望找到往届比赛中排名第三的分数,作为自己的目标。具体规则如下:

  1. 如果分数中有三个或以上不同的分数,返回其中第三大的分数。
  2. 如果不同的分数只有两个或更少,那么小M将选择最大的分数作为他的目标。

请你帮小M根据给定的分数数组计算目标分数。

解题思路

  1. 去重和排序:我们利用set的特性-保存不重复的元素的集合,对数组中的分数进行去重,然后对去重后的分数进行排序。
  2. 判断不同分数的数量:根据去重后的分数数量,判断是否存在第三大的分数。
  3. 返回结果:根据判断结果返回相应的分数。

代码实现

def solution(n: int, nums: list) -> int:
    # 去重
    unique_scores = list(set(nums))
    
    # 排序
    unique_scores.sort()
    
    # 判断不同分数的数量
    if len(unique_scores) >= 3:
        # 返回第三大的分数
        return unique_scores[-3]
    else:
        # 返回最大的分数
        return unique_scores[-1]

31. a替换函数

问题描述

给定一个字符串ss,编写一个函数,将字符串中的小写字母a替换为"%100",并返回替换后的字符串。

例如,对于字符串"abcdwa",所有a字符会被替换为"%100",最终结果为%100bcdw%100"

解题思路

因为字符串是不可变的,所以这里创建一个新的字符串来存储替换后的结果。然后我们遍历字符串中的每一个字符。如果字符是 'a',则将其替换为 "%100"。否则,保持字符不变。

代码实现

def solution(s: str) -> str:
    # 初始化一个空字符串来存储结果
    result = ""
    
    # 遍历字符串中的每一个字符
    for char in s:
        # 如果字符是 'a',则替换为 "%100"
        if char == 'a':
            result += "%100"
        else:
            # 否则,保持字符不变
            result += char
    
    # 返回替换后的字符串
    return result

32. 红包运气排行榜

问题描述

小C参与了一场抢红包的游戏,现在他想要对所有参与抢红包的人进行一次运气排名。排名规则如下:抢到的金额越多,排名越靠前;如果两个人抢到的金额相同,则按照他们抢红包的顺序进行排名。比如,如果小C和小U抢到的金额相同,但小C比小U先抢,则小C排在小U前面。

解题思路

我们先用字典收集每个人抢到的红包的总金额,先抢到红包的人在字典里的位置会靠前。然后我们使用sorted函数对总金额按降序排序。如果总金额相同,就按其在字典里的索引位置排序。或者可以自定义一个稳定的排序算法。

代码实现

def solution(n: int, s: list, x: list) -> list:
    #创建一个字典来记录每个人的总抢红包金额
    total_amount = {}
    
    # 遍历所有抢红包的记录
    for i in range(n):
        name = s[i]
        amount = x[i]
        if name in total_amount:
            total_amount[name] += amount  # 累加每个人的总抢红包金额
        else:
            total_amount[name] = amount  # 插入新的记录
    
    # 将字典转换为列表,并按金额降序排序,金额相同则按名字的原始顺序排序
    sorted_participants = sorted(total_amount.items(), key=lambda item: (-item[1], s.index(item[0])))
    
    # 提取排序后的名字列表
    result = [p[0] for p in sorted_participants]
    
    return result

今天的AI刷题题目解析就到这里,小伙伴们如果有更好的解题思路,欢迎在评论区留言一起交流。