题目解析 | 豆包MarsCode AI刷题

30 阅读4分钟

叠盘子排序

题目理解

题目要求我们将一个有序的整数数组中的元素按照连续递增的序列进行分组,并且每个分组至少包含3个元素。如果一个序列的长度小于3,则该序列中的每个元素应单独列出。

数据结构选择

  • 使用一个列表 result 来存储最终的结果。
  • 使用两个指针 startend 来标记当前连续序列的起始和结束位置。

算法步骤

  1. 初始化一个空列表 result 用于存储结果。
  2. 使用一个指针 i 遍历整个数组 plates
  3. 对于每个元素,检查它是否与下一个元素连续递增。
  4. 如果连续递增,则继续移动 i 直到不再连续递增。
  5. 记录当前连续序列的起始位置 start 和结束位置 end
  6. 如果 end - start >= 2,则将该连续序列作为一个范围加入 result
  7. 否则,将该序列中的每个元素单独加入 result
  8. 继续遍历数组,直到所有元素都被处理。
  9. 最后,将 result 中的元素用逗号连接成一个字符串并返回。

代码实现

def solution(plates: list[int], n: int) -> str:
    result = []
    i = 0
    
    while i < n:
        start = i
        
        # 找到连续序列的结束位置
        while i + 1 < n and plates[i + 1] == plates[i] + 1:
            i += 1
        
        end = i
        
        # 判断序列长度是否大于等于3
        if end - start >= 2:
            result.append(f"{plates[start]}-{plates[end]}")
        else:
            # 将单独的盘子加入结果
            for j in range(start, end + 1):
                result.append(str(plates[j]))
        
        i += 1
    
    return ",".join(result)

代码解释

  • result 列表用于存储最终的结果。
  • i 是遍历数组的指针。
  • startend 用于标记当前连续序列的起始和结束位置。
  • 通过 while 循环找到连续序列的结束位置。
  • 根据序列长度决定是将序列作为一个范围加入 result 还是将每个元素单独加入 result
  • 最后,使用 join 方法将 result 中的元素连接成一个字符串并返回。

最小替换子串长度

问题理解

  • 题目要求我们通过尽可能少的替换操作,使得字符串中字符ASDF的出现频次相等。
  • 字符串的长度总是4的倍数,因此每个字符的目标频次为n // 4,其中n是字符串的长度。

数据结构选择

  • 使用字典current_freq来统计当前字符串中每个字符的出现频次。
  • 使用字典need_change来记录每个字符需要增加或减少的次数,以达到目标频次。

算法步骤

  • 首先,统计字符串中每个字符的当前频次。
  • 计算每个字符需要增加或减少的次数,存储在need_change字典中。
  • 如果所有字符的频次已经相等(即need_change中所有值都为0),则直接返回0。
  • 使用滑动窗口技术来找到最小的子串长度,使得该子串中包含足够多的字符来满足need_change中的需求。
  • 初始化滑动窗口的左边界left为0,右边界right从0开始遍历到字符串的末尾。
  • 在每次扩展右边界时,更新窗口内字符的计数。
  • 当窗口内的字符计数满足need_change中的需求时,尝试缩小左边界,同时更新最小子串长度。

代码实现

def solution(input):
    n = len(input)
    target_freq = n // 4  # 目标频次
    
    # 统计当前频次
    current_freq = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
    for char in input:
        current_freq[char] += 1
    
    # 计算每个字符需要增加或减少的次数
    need_change = {char: max(0, current_freq[char] - target_freq) for char in 'ASDF'}
    
    # 如果所有字符的频次已经相等,直接返回0
    if sum(need_change.values()) == 0:
        return 0
    
    # 滑动窗口初始化
    left = 0
    min_length = n  # 初始化最小长度为整个字符串的长度
    window_count = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
    
    # 扩展右边界
    for right in range(n):
        window_count[input[right]] += 1
        
        # 检查当前窗口是否满足条件
        while all(window_count[char] >= need_change[char] for char in 'ASDF'):
            min_length = min(min_length, right - left + 1)
            window_count[input[left]] -= 1
            left += 1
    
    return min_length

代码解释

  1. 统计当前频次

    current_freq = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
    for char in input:
        current_freq[char] += 1
    

    这部分代码统计了字符串中每个字符的出现频次。

  2. 计算需要增加或减少的次数

    need_change = {char: max(0, current_freq[char] - target_freq) for char in 'ASDF'}
    

    这部分代码计算了每个字符需要增加或减少的次数,以达到目标频次。

  3. 滑动窗口技术

    for right in range(n):
        window_count[input[right]] += 1
        
        while all(window_count[char] >= need_change[char] for char in 'ASDF'):
            min_length = min(min_length, right - left + 1)
            window_count[input[left]] -= 1
            left += 1
    

    这部分代码使用了滑动窗口技术来找到最小的子串长度,使得该子串中包含足够多的字符来满足need_change中的需求。