叠盘子排序

74 阅读5分钟

题目解析

这道题目描述了一个规则化整理数组的过程,要求将输入的整数数组分组,按照一定规则输出。具体来说,每一组数字满足以下条件:

  1. 连续性

    • 每组中的数字是连续递增的,即每两个相邻数字的差值为1。
  2. 长度限制

    • 如果连续递增的数字序列长度 ≥3≥3,需要用范围表示,例如:-3--1
    • 如果序列长度 <3<3,则每个数字都单独输出,例如:2 或 10

目标是将输入的整数数组按照上述规则分组,并以规定的字符串格式输出。


问题分解

输入与输出

  1. 输入

    • 一个整数数组 plates,表示盘子的编号,长度为 n
    • 数组已经按递增顺序排列。
  2. 输出

    • 一个字符串,表示盘子分组后的结果。组之间用逗号分隔:
      • 连续递增长度 ≥3≥3 的组用 start-end 表示。
      • 其他数字直接用其值表示。

分析规则与逻辑

1. 连续递增序列的判断

  • 数字序列的连续递增需要满足 plates[i+1] - plates[i] = 1
  • 遍历数组时可以通过一个指针记录当前的连续起点 start,另一个指针 end 指向当前连续段的终点。
  • 每次比较 plates[end+1] 和 plates[end] 的差值,如果为 1,则继续扩展当前序列;否则,记录该序列并重新开始下一段。

2. 序列长度的判断

  • 当序列长度 (end - start + 1)≥3(end - start + 1)≥3 时,用 start-end 格式输出。
  • 当序列长度 <3<3 时,序列中的数字逐个输出。

3. 字符串拼接

  • 每处理完一个序列,需要将结果拼接到最终输出字符串中。
  • 使用逗号 , 分隔不同序列。
  • 为避免多余的逗号,需特别处理最后一段。

解题步骤

  1. 初始化变量

    • 定义一个字符串构造器 result 来拼接最终结果。
    • 定义指针 start 用于标记当前连续序列的起点。
  2. 遍历数组

    • 从左到右扫描数组,判断每个数字是否与其后续数字连续。
    • 如果连续,将指针 end 向右移动。
    • 如果不连续或到达数组末尾,则判断当前序列的长度并按照规则拼接到结果中。
  3. 处理单独数字与范围

    • 如果序列长度 ≥3≥3,拼接 plates[start]-plates[end]
    • 如果序列长度 <3<3,逐个拼接 plates[start], plates[start+1], ...
  4. 处理最后一个序列

    • 由于遍历结束时可能还有一个未处理的序列,需要在遍历结束后再将剩余的序列处理并拼接到结果中。
  5. 返回结果

    • 将拼接好的字符串作为最终输出。

测试样例分析

样例 1

  • 输入plates = [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20]
  • 分析:
    1. 数组中连续段为:
      • -3, -2, -1:长度为3,输出 -3--1
      • 2:单个数字,输出 2
      • 10:单个数字,输出 10
      • 15, 16:长度为2,输出 15,16
      • 18, 19, 20:长度为3,输出 18-20
    2. 最终输出为:"-3--1,2,10,15,16,18-20"
  • 输出"-3--1,2,10,15,16,18-20"

样例 2

  • 输入plates = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
  • 分析:
    1. 数组中连续段为:
      • -6:单个数字,输出 -6
      • -3, -2, -1, 0, 1:长度为5,输出 -3-1
      • 3, 4, 5:长度为3,输出 3-5
      • 7, 8, 9, 10, 11:长度为5,输出 7-11
      • 14:单个数字,输出 14
      • 15:单个数字,输出 15
      • 17, 18, 19, 20:长度为4,输出 17-20
    2. 最终输出为:"-6,-3-1,3-5,7-11,14,15,17-20"
  • 输出"-6,-3-1,3-5,7-11,14,15,17-20"

样例 3

  • 输入plates = [1, 2, 7, 8, 9, 10, 11, 19]
  • 分析:
    1. 数组中连续段为:
      • 1, 2:长度为2,输出 1,2
      • 7, 8, 9, 10, 11:长度为5,输出 7-11
      • 19:单个数字,输出 19
    2. 最终输出为:"1,2,7-11,19"
  • 输出"1,2,7-11,19"

`public class Main { public static String solution(int[] plates, int n) { StringBuilder result = new StringBuilder(); int start = 0;

    while (start < n) {
        int end = start;
        // 找到一个连续递增的序列
        while (end + 1 < n && plates[end + 1] == plates[end] + 1) {
            end++;
        }

        // 检查序列的长度
        if (end - start >= 2) {
            // 序列长度大于等于3,格式化为范围表示
            result.append(plates[start]).append("-").append(plates[end]);
        } else {
            // 否则单个输出
            for (int i = start; i <= end; i++) {
                result.append(plates[i]);
                if (i != end) {
                    result.append(",");
                }
            }
        }

        // 如果不是最后一个序列,则加上逗号
        if (end + 1 < n) {
            result.append(",");
        }

        // 移动到下一个序列
        start = end + 1;
    }

    return result.toString();
}

public static void main(String[] args) {
    //  You can add more test cases here
    System.out.println(solution(new int[]{-3, -2, -1, 2, 10, 15, 16, 18, 19, 20}, 10).equals("-3--1,2,10,15,16,18-20"));
    System.out.println(solution(new int[]{-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20}, 20).equals("-6,-3-1,3-5,7-11,14,15,17-20"));
    System.out.println(solution(new int[]{1, 2, 7, 8, 9, 10, 11, 19}, 8).equals("1,2,7-11,19"));
}

}`

时间复杂度分析

  1. 遍历数组

    • 数组长度为 nn,每个元素只被访问一次,因此时间复杂度为 O(n)O(n)。
  2. 字符串拼接

    • 字符串拼接操作与连续段数量相关,总复杂度为 O(n)O(n)。
  3. 总体复杂度

    • 时间复杂度为 O(n)O(n),空间复杂度为 O(n)O(n)(用于存储结果字符串)。

总结

本题通过对数组的连续性和长度规则进行分段处理,实现了高效的字符串拼接。算法核心在于利用指针记录连续段的起点和终点,按规则判断是否需要合并成范围或逐一输出。最终解决方案兼顾了效率和易读性,适用于各种长度的输入数组。