本题的任务是构造一个特定数组,规则如下:
- 给定一个数字 nnn,对于每个 iii 从 1 到 nnn,需要将从 nnn 到 iii 的数字按逆序拼接。
- 最终需要输出拼接完成的数组。
示例分析:
-
n=3n = 3n=3:
- i=1i = 1i=1,拼接 [3, 2, 1];
- i=2i = 2i=2,拼接 [3, 2];
- i=3i = 3i=3,拼接 [3];
- 最终数组为 [3, 2, 1, 3, 2, 3]。
-
n=4n = 4n=4:
- i=1i = 1i=1,拼接 [4, 3, 2, 1];
- i=2i = 2i=2,拼接 [4, 3, 2];
- i=3i = 3i=3,拼接 [4, 3];
- i=4i = 4i=4,拼接 [4];
- 最终数组为 [4, 3, 2, 1, 4, 3, 2, 4, 3, 4]。
解题思路
-
动态数组存储结果:
- 由于我们无法事先知道拼接后的数组长度,因此选择使用动态数组(如
ArrayList)存储结果,最后再转换为静态数组(int[])。
- 由于我们无法事先知道拼接后的数组长度,因此选择使用动态数组(如
-
外层循环控制拼接次数:
- 外层循环从 i=1i = 1i=1 到 nnn,每次递增 iii。
- 当前 iii 表示要从 nnn 拼接到 iii。
-
内层循环实现逆序拼接:
- 内层循环从 j=nj = nj=n 到 iii,将数字逐个添加到结果数组中。
-
结果转换:
- 最后将动态数组转化为定长数组并返回。
代码实现
java
复制代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static int[] solution(int n) {
// 用于存储最终结果的动态数组
List<Integer> result = new ArrayList<>();
// 构造数组,外层循环从 1 到 n
for (int i = 1; i <= n; i++) {
// 内层循环从 n 到 i
for (int j = n; j >= i; j--) {
result.add(j);
}
}
// 将动态数组转换为固定大小的 int 数组
return result.stream().mapToInt(Integer::intValue).toArray();
}
public static void main(String[] args) {
System.out.println(Arrays.equals(solution(3), new int[]{3, 2, 1, 3, 2, 3}));
System.out.println(Arrays.equals(solution(4), new int[]{4, 3, 2, 1, 4, 3, 2, 4, 3, 4}));
System.out.println(Arrays.equals(solution(5), new int[]{5, 4, 3, 2, 1, 5, 4, 3, 2, 5, 4, 3, 5, 4, 5}));
}
}
代码解析
-
外层循环:
- 从 i=1i = 1i=1 到 nnn,每次代表当前构造的起点是 iii。
- 每次 iii 控制的是当前逆序数组的下界(停止值)。
-
内层循环:
- 从 j=nj = nj=n 到 iii 遍历,将 jjj 添加到结果列表中。
- 这种方式实现了逆序插入,并且控制了从 nnn 开始到 iii 的子数组。
-
动态数组到定长数组的转换:
- Java 中
ArrayList使用方便,但需要返回固定长度的数组。 - 使用
stream().mapToInt()将List<Integer>转换为int[]。
- Java 中
-
时间复杂度:
- 外层循环运行 nnn 次,内层循环在最坏情况下也运行 nnn 次,因此时间复杂度为 O(n2)O(n^2)O(n2)。
-
空间复杂度:
- 动态数组需要存储最终结果,空间复杂度为 O(n2)O(n^2)O(n2)。
测试用例分析
-
测试用例 1:n=3n = 3n=3
- 外层循环依次处理 i=1,2,3i = 1, 2, 3i=1,2,3。
- 内层循环分别逆序拼接 [3, 2, 1],然后 [3, 2],最后 [3]。
- 最终结果:[3, 2, 1, 3, 2, 3]。
-
测试用例 2:n=4n = 4n=4
- 外层循环依次处理 i=1,2,3,4i = 1, 2, 3, 4i=1,2,3,4。
- 内层循环分别逆序拼接 [4, 3, 2, 1],然后 [4, 3, 2],接着 [4, 3],最后 [4]。
- 最终结果:[4, 3, 2, 1, 4, 3, 2, 4, 3, 4]。
-
测试用例 3:n=5n = 5n=5
- 外层循环依次处理 i=1,2,3,4,5i = 1, 2, 3, 4, 5i=1,2,3,4,5。
- 内层循环分别逆序拼接 [5, 4, 3, 2, 1],然后 [5, 4, 3, 2],接着 [5, 4, 3],再 [5, 4],最后 [5]。
- 最终结果:[5, 4, 3, 2, 1, 5, 4, 3, 2, 5, 4, 3, 5, 4, 5]。
进一步优化方向
-
内存优化:
- 可以在计算结果大小时预先分配足够的空间,从而避免动态数组扩容的开销。
-
并行计算:
- 在一些特殊场景中,可以考虑使用多线程并行生成子数组。
-
生成规律:
- 如果有需要,也可以通过数学规律直接生成结果,从而减少循环次数。
学习总结
-
分解问题:
- 通过题目规则拆解,逐步实现各个部分逻辑(外层循环、内层循环等)。
-
动态数据结构的灵活应用:
- 使用
ArrayList方便地动态扩展存储内容,同时利用其流式操作转换为固定数组。
- 使用
-
性能与扩展性:
- 时间和空间复杂度均是常见的 O(n2)O(n^2)O(n2) 问题,后续优化可考虑预计算或规律生成。
这道题目通过简单的规则,实现了对循环和嵌套逻辑的良好练习,同时帮助理解如何动态处理数组生成问题。
4o