构造特定数组的逆序拼接| 豆包MarsCode AI刷题

61 阅读3分钟

问题解析:
小U面临的任务是生成一个特定规则的数组。这个数组的生成规则是:从数字 n 开始,逐渐逆序拼接到 1,依次构造多个部分数组,然后将它们按照顺序拼接在一起。最终,我们需要输出这个完整的数组。具体来说,对于输入的 n,结果数组的长度为 n×(n+1)2\frac{n \times (n + 1)}{2},即随着 n 的增大,数组的长度呈现二次增长。因此,这道题的关键在于如何高效地生成这些部分数组并完成拼接。

例如,当 n = 3 时,生成的结果数组为 [3, 2, 1, 3, 2, 3]。可以看出,它由以下部分数组构成:

  • 第1部分:从 31,结果为 [3, 2, 1]
  • 第2部分:从 32,结果为 [3, 2]
  • 第3部分:从 33,结果为 [3]
    将这些部分数组按顺序拼接在一起,就得到最终结果。

解题思路:

  1. 构造部分数组:
    每次从 n 开始,逆序生成到当前的 i(其中 1≤i≤n1 \leq i \leq n)。

    • 第一次生成从 n1 的完整逆序数组。
    • 第二次生成从 n2 的部分数组。
    • 依此类推,直到第 n 次,仅包含 n 自身。
      这些部分数组彼此独立,但拼接后的顺序影响最终结果。
  2. 拼接数组:
    使用一个结果数组存储每次生成的部分数组。通过 extend 方法将部分数组高效地拼接到结果数组中,避免逐个元素插入带来的额外开销。

  3. 优化拼接逻辑:
    在每次生成部分数组时,通过构造列表的方式(如使用 range)减少不必要的循环,直接生成需要的逆序序列。

  4. 代码实现:
    将上述思路转化为代码,并保证其可读性和高效性。


代码实现:

def solution(n: int) -> list:
    # 初始化结果数组
    result = []
    
    # 逐步生成从 n 到 i 的部分数组
    for i in range(1, n + 1):
        # 生成从 n 到 i 的逆序部分数组
        sub_array = list(range(n, i - 1, -1))
        # 将部分数组拼接到结果数组
        result.extend(sub_array)
    
    return result

测试代码:

if __name__ == '__main__':
    print(solution(3) == [3, 2, 1, 3, 2, 3])  # 测试用例1
    print(solution(4) == [4, 3, 2, 1, 4, 3, 2, 4, 3, 4])  # 测试用例2
    print(solution(5) == [5, 4, 3, 2, 1, 5, 4, 3, 2, 5, 4, 3, 5, 4, 5])  # 测试用例3

复杂度分析:

  1. 时间复杂度:

    • 每次生成部分数组的时间复杂度为 O(n−i+1)O(n - i + 1)。
    • 总体复杂度为 O(n+(n−1)+(n−2)+...+1)=O(n2)O(n + (n-1) + (n-2) + ... + 1) = O(n^2) 因此,时间复杂度为 O(n2)O(n^2)。
  2. 空间复杂度:

    • 结果数组需要存储所有拼接后的元素,长度为 n×(n+1)2\frac{n \times (n + 1)}{2}。
    • 因此,空间复杂度为 O(n2)O(n^2)。

解题思考:

  1. 解决核心问题:
    这道题的难点在于生成部分数组和拼接的逻辑。通过直接使用 range 函数,简化了部分数组的生成过程,同时利用 extend 方法高效地拼接结果数组。

  2. 问题优化方向:

    • 对于生成完整数组的场景,由于需要存储所有元素,空间复杂度很难进一步优化。
    • 如果问题变为仅查询某个特定位置的值(例如索引 k 对应的元素值),可以直接计算所在的部分数组并定位值,从而避免生成整个结果数组。
  3. 问题的拓展思路:

    • 如果数组规模变得极大(例如 n>106n > 10^6),可以通过生成器函数(如 yield)动态生成部分数组,减少内存占用。
    • 问题可以进一步延伸到不同的拼接规则,例如按升序或间隔跳跃生成部分数组。