构造特定数组问题 | 豆包MarsCode AI刷题

81 阅读4分钟

本题的任务是构造一个特定数组,规则如下:

  • 给定一个数字 nnn,对于每个 iii 从 1 到 nnn,需要将从 nnn 到 iii 的数字按逆序拼接。
  • 最终需要输出拼接完成的数组。

示例分析:

  1. 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]。
  2. 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]。

解题思路

  1. 动态数组存储结果:

    • 由于我们无法事先知道拼接后的数组长度,因此选择使用动态数组(如 ArrayList)存储结果,最后再转换为静态数组(int[])。
  2. 外层循环控制拼接次数:

    • 外层循环从 i=1i = 1i=1 到 nnn,每次递增 iii。
    • 当前 iii 表示要从 nnn 拼接到 iii。
  3. 内层循环实现逆序拼接:

    • 内层循环从 j=nj = nj=n 到 iii,将数字逐个添加到结果数组中。
  4. 结果转换:

    • 最后将动态数组转化为定长数组并返回。

代码实现

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}));
    }
}

代码解析

  1. 外层循环:

    • 从 i=1i = 1i=1 到 nnn,每次代表当前构造的起点是 iii。
    • 每次 iii 控制的是当前逆序数组的下界(停止值)。
  2. 内层循环:

    • 从 j=nj = nj=n 到 iii 遍历,将 jjj 添加到结果列表中。
    • 这种方式实现了逆序插入,并且控制了从 nnn 开始到 iii 的子数组。
  3. 动态数组到定长数组的转换:

    • Java 中 ArrayList 使用方便,但需要返回固定长度的数组。
    • 使用 stream().mapToInt()List<Integer> 转换为 int[]
  4. 时间复杂度:

    • 外层循环运行 nnn 次,内层循环在最坏情况下也运行 nnn 次,因此时间复杂度为 O(n2)O(n^2)O(n2)。
  5. 空间复杂度:

    • 动态数组需要存储最终结果,空间复杂度为 O(n2)O(n^2)O(n2)。

测试用例分析

  1. 测试用例 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. 测试用例 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. 测试用例 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]。

进一步优化方向

  1. 内存优化:

    • 可以在计算结果大小时预先分配足够的空间,从而避免动态数组扩容的开销。
  2. 并行计算:

    • 在一些特殊场景中,可以考虑使用多线程并行生成子数组。
  3. 生成规律:

    • 如果有需要,也可以通过数学规律直接生成结果,从而减少循环次数。

学习总结

  1. 分解问题:

    • 通过题目规则拆解,逐步实现各个部分逻辑(外层循环、内层循环等)。
  2. 动态数据结构的灵活应用:

    • 使用 ArrayList 方便地动态扩展存储内容,同时利用其流式操作转换为固定数组。
  3. 性能与扩展性:

    • 时间和空间复杂度均是常见的 O(n2)O(n^2)O(n2) 问题,后续优化可考虑预计算或规律生成。

这道题目通过简单的规则,实现了对循环和嵌套逻辑的良好练习,同时帮助理解如何动态处理数组生成问题。

4o