叠盘子——题目解析及解题

118 阅读4分钟

问题背景

小M喜欢用一种特别的方式整理他家里的盘子。每当用餐完毕后,他会将盘子按照它们的序号顺序叠放起来。这些盘子的序号都是独一无二的整数,并且在开始整理之前已经是递增排列的了。小M叠放盘子的规则是:每一堆盘子的序号必须是连续递增的,并且每堆至少要有三个盘子。如果不能满足这个条件,那么这些盘子就需要单独列出。

输入输出示例

  • 样例1:

    • 输入:plates = [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20], n = 10
    • 输出:"-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], n = 20
    • 输出:"-6,-3-1,3-5,7-11,14,15,17-20"
  • 样例3:

    • 输入:plates = [1, 2, 7, 8, 9, 10, 11, 19], n = 8
    • 输出:"1,2,7-11,19"

解题思路

这个问题的核心在于识别出哪些盘子可以组成一组(即连续递增且至少有三个盘子),以及如何处理那些不能形成组的单个盘子或盘子对。我们可以通过遍历给定的盘子列表来实现这一目标,同时记录当前连续序列的起始位置和结束位置。当遇到不连续的情况时,检查已记录的序列是否符合组的要求,然后重置起始和结束位置以开始新的序列。

代码解析

#include <iostream>
#include <string>
#include <vector>

// 主要的解决方案函数
std::string solution(std::vector<int> &plates, int n) {
  std::string result = ""; // 初始化结果字符串
  int start = 0; // 当前连续序列的起始索引
  int end = 0;   // 当前连续序列的结束索引

  // 遍历盘子列表
  for (int i = 1; i < n; ++i) {
    if (plates[i] == plates[i - 1] + 1) { // 检查当前盘子是否与前一个盘子连续
      end = i; // 更新结束索引
    } else { // 如果不连续
      if (end - start >= 2) { // 检查连续序列是否至少有3个盘子
        result += std::to_string(plates[start]) + "-" + std::to_string(plates[end]) + ","; // 添加到结果中
      } else { // 如果序列小于3个盘子
        for (int j = start; j <= end; ++j) { // 将每个盘子单独添加到结果中
          result += std::to_string(plates[j]) + ",";
        }
      }
      // 重新设置起始和结束索引
      start = i;
      end = i;
    }
  }

  // 处理最后一个序列
  if (end - start >= 2) {
    result += std::to_string(plates[start]) + "-" + std::to_string(plates[end]);
  } else {
    for (int j = start; j <= end; ++j) {
      result += std::to_string(plates[j]) + ",";
    }
  }

  // 删除结果字符串末尾多余的逗号
  if (!result.empty() && result.back() == ',') {
    result.pop_back();
  }

  return result; // 返回最终的结果
}

定义解决方案函数

cpp
std::string solution(std::vector<int> &plates, int n) {
  std::string result = ""; // 初始化结果字符串
  int start = 0; // 当前连续序列的起始索引
  int end = 0;   // 当前连续序列的结束索引
  • std::string result = "":初始化一个空字符串,用于存储最终的结果。
  • int start = 0:初始化当前连续序列的起始索引。
  • int end = 0:初始化当前连续序列的结束索引。

遍历盘子列表

cpp
for (int i = 1; i < n; ++i) {
  if (plates[i] == plates[i - 1] + 1) { // 检查当前盘子是否与前一个盘子连续
    end = i; // 更新结束索引
  } else { // 如果不连续
    if (end - start >= 2) { // 检查连续序列是否至少有3个盘子
      result += std::to_string(plates[start]) + "-" + std::to_string(plates[end]) + ","; // 添加到结果中
    } else { // 如果序列小于3个盘子
      for (int j = start; j <= end; ++j) { // 将每个盘子单独添加到结果中
        result += std::to_string(plates[j]) + ",";
      }
    }
    // 重新设置起始和结束索引
    start = i;
    end = i;
  }
}
  • for (int i = 1; i < n; ++i):从第二个盘子开始遍历整个列表。

  • if (plates[i] == plates[i - 1] + 1):检查当前盘子是否与前一个盘子连续。

    • 如果连续,更新 end 为当前索引 i
  • else:如果不连续,处理当前连续序列。

    • if (end - start >= 2):检查当前连续序列是否至少有3个盘子。

      • 如果是,将该序列格式化为 start-end 并添加到结果字符串中。
    • else:如果序列小于3个盘子。

      • 使用一个内循环将每个盘子单独添加到结果字符串中。
  • start = i; end = i;:更新 start 和 end 为当前索引 i,开始新的序列。

处理最后一个序列

cpp
if (end - start >= 2) {
  result += std::to_string(plates[start]) + "-" + std::to_string(plates[end]);
} else {
  for (int j = start; j <= end; ++j) {
    result += std::to_string(plates[j]) + ",";
  }
}
  • if (end - start >= 2):检查最后一个序列是否至少有3个盘子。

    • 如果是,将该序列格式化为 start-end 并添加到结果字符串中。
  • else:如果序列小于3个盘子。

    • 使用一个内循环将每个盘子单独添加到结果字符串中。

删除结果字符串末尾多余的逗号

cpp
深色版本
if (!result.empty() && result.back() == ',') {
  result.pop_back();
}
  • if (!result.empty() && result.back() == ','):检查结果字符串是否非空且最后一个字符是逗号。

    • 如果是,删除最后一个字符(逗号)。

返回结果