问题背景
小U需要构造一个数组,满足一定的规则:
- 给定一个正整数 (n),需要从 (n) 到 (1) 按逆序拼接数组。
- 在完成一次逆序拼接后,继续去掉序列最右的数字,直到只剩下一个数字为止。
- 最终的输出是多个拼接后的部分按顺序依次追加的数组。
示例分析
我们通过示例来逐步解析题意:
示例 1
- 输入:(n = 3)
- 拼接过程:
- 第一步,从 (3) 到 (1):[3, 2, 1]
- 第二步,从 (3) 到 (2):[3, 2]
- 第三步,从 (3) 到 (3):[3]
- 输出:最终数组是 [3, 2, 1, 3, 2, 3]
示例 2
- 输入:(n = 4)
- 拼接过程:
- 第一步,从 (4) 到 (1):[4, 3, 2, 1]
- 第二步,从 (4) 到 (2):[4, 3, 2]
- 第三步,从 (4) 到 (3):[4, 3]
- 第四步,从 (4) 到 (4):[4]
- 输出:最终数组是 [4, 3, 2, 1, 4, 3, 2, 4, 3, 4]
题目抽象
对任意 (n):
- 对于每个 (i) 从 1 到 (n):将 ([n, n-1, \dots, i]) 拼接至结果数组。
- 每次递减 (i),以保留一个逐步缩减的递归式构造。
- 最终返回一个完整拼接的数组。
算法核心可以总结为:双重嵌套循环 + 动态数组拼接。
解题思路
-
确定主循环逻辑:
- 反向构造是从 (n) 到 (i),因此我们需要在外层对 (i) 从 (1) 遍历到 (n)。
- 内层则是简单构造从 (n) 到 (i) 的递减序列。
-
模拟拼接过程:
- 可以使用 Python 中的列表 (list),每次将一段生成的数组延展至最终结果。
-
算法复杂度分析:
- 外层循环执行 (n) 次,内层每次生成的序列长度为 (n, n-1, \dots, 1)。
- 时间复杂度:(O(n^2))。
- 空间复杂度:结果数组占用 (O(n^2)) 的额外空间。
图解拼接过程
以 (n = 4) 为例,构造如下:
-
初始时 (i = 1):结果为 [4, 3, 2, 1]
-
第二步 (i = 2):拼接 [4, 3, 2]
-
第三步 (i = 3):拼接 [4, 3]
-
第四步 (i = 4):拼接 [4]
最终拼接完成,结果为 [4, 3, 2, 1, 4, 3, 2, 4, 3, 4]。
代码实现
# 定义构造数组的函数
def solution(n):
result = [] # 存储最终结果
for i in range(1, n + 1):
# 拼接从 n 到 i 的部分数组
result.extend(range(n, i - 1, -1))
return result
# 测试样例
if __name__ == "__main__":
n1 = 3
print(solution(n1)) # 输出:[3, 2, 1, 3, 2, 3]
n2 = 4
print(solution(n2)) # 输出:[4, 3, 2, 1, 4, 3, 2, 4, 3, 4]
代码详解
result = []
:- 定义一个空列表,存储最终构造的数组。
for i in range(1, n + 1):
:- 从 (i = 1) 遍历到 (n),逐步构造拼接段。
range(n, i - 1, -1)
:- 使用
range
函数生成从 (n) 到 (i) 的递减序列。
- 使用
result.extend(...)
:- 将每次生成的序列追加到结果数组。
- 返回拼接完成的结果数组。
思考与优化
优化思路
目前算法的主要瓶颈在于:
- 每次
range
生成新序列,存在重复创建的开销。 - 多次拼接操作可能导致空间重新分配。
可以进一步优化:
- **提前生成完整序列表:**使用倒序直接操作。
- **合并数组拼接逻辑:**减少 Python 内部动态分配的次数。
替代方法
采用列表推导式优化拼接:
def construct_array_optimized(n):
return [x for i in range(1, n + 1) for x in range(n, i - 1, -1)]
通过嵌套的列表推导式,生成最终数组,效率更高。