问题描述
小M有一个独特的方式来收拾家中的盘子。每次用餐后,他会将盘子按照他们的序号顺序叠放。盘子的序号都是唯一的整数,并且在收拾前就是递增的。小M的叠放规则是,每一堆盘子的序号都是连续递增的,并且至少包含3个盘子。需要编写程序帮助小M确定盘子的叠放方式。
例如,输入的盘子序号是 [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20],按照小M的规则,连续递增序列 -3, -2, -1 可以叠在一起表示为 -3--1,而 18, 19, 20 可以叠在一起表示为 18-20。不满足连续递增至少3个的,如 2, 10, 15, 16 都应单独列出。
输入参数
plates: 一个整数数组,表示盘子的序号n: 盘子总数
测试样例
样例1:
输入:
plates = [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20], n = 10
输出:"-3--1,2,10,15,16,18-20"
这个问题的关键是使用双指针来找到连续的子序列,并将它们合并成符合要求的格式。具体步骤如下:
思路:
- 双指针的应用:通过两个指针遍历盘子的序号数组。一个指针指向当前序列的起始位置,另一个指针不断向后移动,直到找到不连续的盘子序号或遇到数组结束。
- 条件判断:当一个连续递增的序列长度大于等于3时,将这个子序列合并为一个范围(例如
-3--1);否则,将其作为单个盘子的序号添加。 - 输出格式:使用逗号将结果连接起来,确保输出符合要求。
具体步骤:
- 初始化一个指针
i用来表示当前处理的盘子序号的起始位置。 - 遍历整个数组,对于每个盘子
plates[i],判断它是否是一个连续递增序列的一部分。 - 如果当前序列长度大于等于3,将其表示为范围(例如
-3--1);否则,将其单独列出。 - 使用逗号连接最终的结果。
-
C++ 实现代码:
std::string solution(std::vector<int> &plates, int n) {
string result; // 用来存储最终的结果
int i = 0; // 双指针的起始位置
while (i < n) {
int j = i;
// 找到连续递增序列的结束位置
while (j + 1 < n && plates[j + 1] == plates[j] + 1) {
j++;
}
// 如果长度大于等于3,表示可以合并为一个范围
if (j - i >= 2) {
result +=to_string(plates[i]) + "-" + to_string(plates[j]);
} else {
// 否则单独列出
for (int k = i; k <= j; k++) {
if (k > i) result +=","; // 在单独的盘子之间添加逗号
result +=to_string(plates[k]);
}
}
// 移动到下一个新的起始位置
i = j + 1;
if (i < n) result += ","; // 逗号分隔不同的部分
}
cout<<result<<endl;
return result;
}
代码解释:
- 该函数接受盘子的序号数组和总盘子数
n,并返回一个格式化的字符串表示叠放方式。 - 双指针:我们用
i作为起始位置,j用来找到连续递增序列的结束位置。对于每一段连续的递增序列,如果其长度大于等于3,则以范围的方式输出,否则单独列出。 - 拼接字符串:使用
to_string来构建结果字符串。我们通过逗号将各个部分连接起来,确保格式正确。 - 输出:在主函数中,我们调用
solution并输出最终的结果。
示例:
输入:
cpp
plates = {-3, -2, -1, 2, 10, 15, 16, 18, 19, 20}
n = 10
输出:
"-3--1,2,10,15,16,18-20"
复杂度分析:
- 时间复杂度:我们只遍历一次盘子序号数组,时间复杂度是 O(n),其中 n 是盘子的数量。
- 空间复杂度:我们使用了
string来存储结果,空间复杂度是 O(n),因为最终结果的大小最多为O(n)。
总结:
通过双指针技术,可以高效地找到连续的递增子序列,并且根据题目要求格式化输出。该算法的时间复杂度较低,适合处理较大规模的输入数据。本题就是对双指针的应用,写的时候注意一些细节,分清楚情况,千万不要把思维弄乱了,今天就到这了,拜拜。