学习方法与心得-易74-叠盘子排序问题-Java实现 | 豆包MarsCode AI刷题

39 阅读4分钟

盘子叠放问题解析

问题描述

小M有一个独特的方式来收拾家中的盘子。每次用餐后,他会将盘子按照它们的序号顺序叠放。盘子的序号都是唯一的整数,并且在收拾前就是递增的。小M的叠放规则是,每一堆盘子的序号都是连续递增的,并且至少包含3个盘子。

需要编写程序帮助小M确定盘子的叠放方式。

示例:

  • 输入plates = [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20], n = 10
  • 输出"-3--1,2,10,15,16,18-20"

连续递增序列 -3, -2, -1 可以叠在一起表示为 -3--1,而 18, 19, 20 可以叠在一起表示为 18-20。不满足连续递增至少3个的,如 2, 10, 15, 16,都应单独列出。

解题思路

为了满足小M的叠放规则,需要遍历盘子的序号数组,识别连续递增的序列,并根据序列长度决定如何表示:

  1. 初始化变量

    • 使用一个变量 start 标记当前连续序列的起始位置。
    • 使用 StringBuilder 来构建最终的输出字符串。
  2. 遍历数组

    • 从第二个元素开始遍历数组,比较当前元素和前一个元素的差值。
    • 如果差值为1,表示序号是连续的,继续遍历。
  3. 确定序列的结束

    • 当发现当前元素和前一个元素不连续,或者已经遍历到数组末尾时,需要处理当前的连续序列。

    • 根据序列长度进行不同的处理:

      • 长度大于等于3:表示为 start-end,例如 -3--1
      • 长度为2:单独列出每个盘子的序号,使用逗号分隔,例如 15,16
      • 长度为1:直接输出该盘子的序号。
  4. 更新起始位置

    • 在处理完当前序列后,更新 start 为当前元素的位置,继续检查后续的盘子。
  5. 构建结果字符串

    • 在每次处理序列时,将结果添加到 StringBuilder 中,并在末尾添加逗号。
    • 遍历结束后,删除最后一个多余的逗号。

代码详解

下面是实现上述思路的 Java 代码:

public static String solution(int[] plates, int n) {
    // 如果输入为空或长度为 0,直接返回空字符串
    if (plates == null || n == 0) {
        return "";
    }

    StringBuilder result = new StringBuilder();
    int start = 0; // 当前连续序列的起始位置

    // 遍历 plates 数组
    for (int i = 1; i <= n; i++) {
        // 如果到达数组末尾,或者当前元素和前一个元素不连续
        if (i == n || plates[i] - plates[i - 1] != 1) {
            if (i - start >= 3) {
                // 序列长度大于等于 3,使用 "start-end" 表示
                result.append(plates[start]).append("-").append(plates[i - 1]).append(",");
            } else {
                // 序列长度小于 3,单独输出每个元素
                for (int j = start; j < i; j++) {
                    result.append(plates[j]).append(",");
                }
            }
            start = i; // 更新起始位置
        }
    }

    // 删除最后一个多余的逗号
    if (result.length() > 0) {
        result.deleteCharAt(result.length() - 1);
    }
    return result.toString();
}

代码解释

  • 主要步骤

    1. 输入检查

      if (plates == null || n == 0) {
          return "";
      }
      
      • 如果输入为空或盘子数量为 0,返回空字符串。
    2. 初始化变量

      StringBuilder result = new StringBuilder();
      int start = 0;
      
      • result 用于构建最终的输出字符串。
      • start 标记当前连续序列的起始位置。
    3. 遍历数组

      for (int i = 1; i <= n; i++) {
      
      • 从索引 1 开始遍历到 n,注意这里使用 <= n,以便在数组末尾处理最后的序列。
    4. 检测序列结束条件

      if (i == n || plates[i] - plates[i - 1] != 1) {
      
      • 当到达数组末尾,或者当前元素和前一个元素不连续时,处理当前序列。
    5. 根据序列长度处理

      • 序列长度大于等于 3

        if (i - start >= 3) {
            result.append(plates[start]).append("-").append(plates[i - 1]).append(",");
        }
        
        • 使用 "start-end" 的格式添加到结果中。
      • 序列长度小于 3

        else {
            for (int j = start; j < i; j++) {
                result.append(plates[j]).append(",");
            }
        }
        
        • 逐个添加序列中的盘子序号。
    6. 更新起始位置

      start = i;
      
      • 准备处理下一个序列。
    7. 删除最后一个逗号

      if (result.length() > 0) {
          result.deleteCharAt(result.length() - 1);
      }
      
      • 确保输出格式正确,没有多余的逗号。

结论

该算法的时间复杂度为 O(n),因为只需要一次遍历即可完成所有操作。


作者:AWM