青训营X豆包MarsCode技术训练营第二课|豆包MarsCode AI刷题

52 阅读6分钟

方向一:学习方法与心得

一、题目描述

问题描述

小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌,播放后将其从歌单中移除。如果歌单中还有歌曲,则会将当前第一首歌移到最后一首。这个过程会一直重复,直到歌单中没有任何歌曲。

例如,给定歌单 [5, 3, 2, 1, 4],真实的播放顺序是 [5, 2, 4, 1, 3]

保证歌曲中的id两两不同。


测试样例

样例1:

输入:n = 5 ,a = [5, 3, 2, 1, 4]
输出:[5, 2, 4, 1, 3]

样例2:

输入:n = 4 ,a = [4, 1, 3, 2]
输出:[4, 3, 1, 2]

样例3:

输入:n = 6 ,a = [1, 2, 3, 4, 5, 6]
输出:[1, 3, 5, 2, 6, 4]

二、题目解析

1、题目理解

本题描述了一种特殊的歌曲播放规则,给定一个包含不同歌曲ID的歌单。播放过程是先播放歌单中的第一首歌,然后将其从歌单移除;若歌单还有歌曲,就把当前的第一首歌移到最后一首,如此循环直至歌单为空,要求根据给定的歌单得出按照这种规则的真实播放顺序。

2、输入输出分析

  • 输入: - 一个整数 n,代表歌单中歌曲的数量。 - 一个长度为 n 的整数数组 a,数组中的元素代表歌曲的ID,且保证两两不同,也就是每个歌曲ID都是唯一的,这个数组就是原始的歌单。
  • -输出: - 一个整数数组,按照题目所描述的特殊播放规则得到的真实播放顺序。

3、示例分析 以样例1为例:

  • 输入 n = 5a = [5, 3, 2, 1, 4]。 - 首先播放第一首歌 5,此时歌单变为 [3, 2, 1, 4]
  • 然后把当前第一首歌 3 移到最后,歌单变为 [2, 1, 4, 3],接着播放第一首歌 2,歌单变为 [1, 4, 3]
  • 再把当前第一首歌 1 移到最后,歌单变为 [4, 3, 1],播放第一首歌 4,歌单变为 [3, 1]
  • 把当前第一首歌 3 移到最后,歌单变为 [1, 3],播放第一首歌 1,歌单变为 [3]。 - 最后播放剩下的唯一一首歌 3
  • 所以真实播放顺序是 [5, 2, 4, 1, 3]。 样例2和样例3也遵循同样的规则进行播放顺序的确定。

4、解题思路提示

可以考虑使用数据结构来模拟这个播放过程。比如,可以利用队列(Queue)数据结构,它遵循先进先出的原则,很适合模拟歌单中歌曲的播放和移动操作。 首先将歌单中的歌曲依次入队,然后按照规则进行循环操作:每次取出队首元素作为播放的歌曲,输出到结果数组中,然后将队首元素出队,如果队列不为空,就把新的队首元素取出并重新加入队尾,如此反复直到队列为空,最终得到的结果数组就是按照特殊规则的播放顺序。 综上所述,本题主要考察对特定规则的理解和运用合适的数据结构来模拟操作以得到正确结果的能力。

三、代码展示

from collections import deque

def solution(n: int, a: list) -> list:
    # 初始化队列
    queue = deque(a)
    result = []
    
    # 当队列不为空时,继续播放歌曲
    while queue:
        # 取出队列前端的歌曲并播放
        current_song = queue.popleft()
        result.append(current_song)
        
        # 如果队列中还有歌曲,将当前队列的前端歌曲移到队列的末尾
        if queue:
            next_song = queue.popleft()
            queue.append(next_song)
    
    return result

if __name__ == '__main__':
    print(solution(n = 5, a = [5, 3, 2, 1, 4]) == [5, 2, 4, 1, 3])
    print(solution(n = 4, a = [4, 1, 3, 2]) == [4, 3, 1, 2])
    print(solution(n = 6, a = [1, 2, 3, 4, 5, 6]) == [1, 3, 5, 2, 6, 4])

四、总结分析

1、代码结构

  • 导入模块: - 首先从 collections 模块中导入了 deque 类,deque 是一种双端队列数据结构,在本题中用于模拟歌单,方便进行歌曲的取出(播放)和移动操作。
  • 函数定义: - 定义了名为 solution 的函数,它接受两个参数: - n:一个整数,表示歌单中歌曲的数量。
  • a:一个列表,包含了歌单中歌曲的ID,且保证元素两两不同。
  • 函数内部实现了按照特定规则确定播放顺序的逻辑:
  • 初始化一个 deque 队列 queue,并将输入的歌单列表 a 中的元素依次添加到队列中。同时初始化一个空列表 result,用于存储最终的播放顺序。
  • 通过一个 while 循环,只要队列 queue 不为空,就进行以下操作:
  • 首先使用 queue.popleft() 取出队列前端的歌曲,将其赋值给 current_song,并添加到 result 列表中,模拟播放这首歌曲并记录播放顺序。
  • 然后判断如果队列 queue 中还有歌曲(即 queue 不为空),再次使用 queue.popleft() 取出当前队列前端的歌曲,赋值给 next_song,接着使用 queue.append(next_song) 将该歌曲移到队列的末尾,模拟将当前第一首歌移到最后一首的规则操作。
  • 最后,函数返回 result 列表,即按照特定规则得到的歌单真实播放顺序。
  • 主程序部分: - 在 if __name__ == '__main__': 语句块中,通过调用 solution 函数并与预期的正确播放顺序进行比较,使用 print 语句输出比较结果,以此来验证 solution 函数对于不同输入样例的正确性。

2、代码优点

  • 清晰的逻辑实现:通过使用 deque 数据结构和简单的循环操作,清晰地模拟了题目所描述的歌曲播放和移动规则,代码逻辑易于理解。
  • 模块化测试:在主程序部分通过对不同输入样例进行函数调用和结果验证,方便对代码功能进行测试,确保函数在各种情况下都能正确输出符合规则的播放顺序。

3、可能的改进点

  • 输入验证:代码目前没有对输入的 na 进行有效性验证,例如 n 是否与 a 的长度匹配,a 中的元素是否确实两两不同等。可以添加一些输入验证逻辑来提高代码的健壮性。
  • 代码复用性:如果在其他场景下也需要类似的按照特定规则处理列表元素的功能,可以考虑将 solution 函数进一步抽象化,使其更具通用性,以便于在不同项目中复用。 总体而言,这段代码有效地实现了根据给定规则确定歌单真实播放顺序的功能,但在输入验证和代码复用性方面还有一定的提升空间。