目录
一、叠盘子排序
问题描述
小明是个讲究生活质量的人,家里的一切都井井有条,比如说家中的盘子都是一个系列,每个盘子都标有唯一的一个整数作为标识。在每次吃完饭后,小明都会将这些盘子按照特定的顺序叠放收拾起来,收拾的规则如下:
- 盘子叠放后会被分为多堆,每一堆都可能是由一个或多个盘子组成
- 叠放在同一堆的盘子的序号都是不间断递增的(例如 1,2,3 为不间断递增,而 1,3,4 则只是普通的递增),并且这些盘子的数量至少是 3 个
- 这些盘子的序号在被叠放之前就是递增的
请问你可以编写一个程序,帮助小明算一算盘子该如何叠放么?
输入格式
空格分隔输入所有的数字
输出格式
一个字符串,每个堆被逗号分隔开,如果堆中只有一个盘子,就用序号表达;如果堆中有多个盘子,用『起始编号』+『-』+『终止编号』来表达。
输入样例(1)
-3 -2 -1 2 10 15 16 18 19 20
输出样例(1)
"-3--1,2,10,15,16,18-20"
输入样例(2)
-6 -3 -2 -1 0 1 3 4 5 7 8 9 10 11 14 15 17 18 19 20
输出样例(2)
"-6,-3-1,3-5,7-11,14,15,17-20"
输入样例(3)
1 2 7 8 9 10 11 19
输出样例(3)
"1,2,7-11,19"
解题思路:
问题理解
- 输入:一个整数序列,表示盘子的标识。
- 输出:一个字符串,表示盘子的叠放方式。
- 规则:
- 盘子需要被分成多个堆。
- 每个堆中的盘子序号是不间断递增的,并且至少有3个盘子。
- 如果堆中只有一个盘子,直接输出该盘子的序号。
- 如果堆中有多个盘子,输出起始编号和终止编号,用“-”连接。
数据结构选择
- 使用一个字符串来存储最终的输出结果。
- 使用一个变量来记录当前堆的起始编号。
- 使用一个变量来记录当前堆的终止编号。
算法步骤
-
初始化:
- 将第一个盘子的序号作为当前堆的起始编号。
- 将第一个盘子的序号作为当前堆的终止编号。
-
遍历盘子序列:
- 如果当前盘子的序号是前一个盘子的序号加1,则更新当前堆的终止编号。
- 如果当前盘子的序号不是前一个盘子的序号加1,则判断当前堆的长度:
- 如果长度大于等于3,将当前堆的起始编号和终止编号加入结果字符串。
- 如果长度小于3,将当前堆的所有盘子序号逐个加入结果字符串。
- 更新当前堆的起始编号和终止编号为当前盘子的序号。
-
处理最后一个堆:
- 在遍历结束后,处理最后一个堆,判断其长度并加入结果字符串。
最终代码:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
std::string solution(std::vector<int> &plates, int n) {
string s = "";
if (plates.empty()) return s;
int start = plates[0]; // 当前堆的起始编号
int end = plates[0]; // 当前堆的终止编号
for (int i = 1; i < plates.size(); i++) {
if (plates[i] == end + 1) {
// 如果当前盘子是前一个盘子的序号加1,更新终止编号
end = plates[i];
} else {
// 否则,处理当前堆
if (end - start >= 2) {
// 如果堆的长度大于等于3
s += to_string(start) + "-" + to_string(end) + ",";
} else {
// 如果堆的长度小于3
for (int j = start; j <= end; j++) {
s += to_string(j) + ",";
}
}
// 更新起始和终止编号
start = plates[i];
end = plates[i];
}
}
// 处理最后一个堆
if (end - start >= 2) {
s += to_string(start) + "-" + to_string(end);
} else {
for (int j = start; j <= end; j++) {
s += to_string(j) + ",";
}
}
// 去掉最后一个逗号
if (!s.empty() && s.back() == ',') {
s.pop_back();
}
return s;
}
int main() {
// You can add more test cases here
std::vector<int> plates1 = {-3, -2, -1, 2, 10, 15, 16, 18, 19, 20};
std::cout << (solution(plates1, 10) == "-3--1,2,10,15,16,18-20") << std::endl;
std::vector<int> plates2 = {-6, -3, -2, -1, 0, 1, 3, 4, 5, 7,
8, 9, 10, 11, 14, 15, 17, 18, 19, 20};
std::cout << (solution(plates2, 20) == "-6,-3-1,3-5,7-11,14,15,17-20")
<< std::endl;
std::vector<int> plates3 = {1, 2, 7, 8, 9, 10, 11, 19};
std::cout << (solution(plates3, 8) == "1,2,7-11,19") << std::endl;
return 0;
}
运行结果:
二、分组飞行棋棋子
问题描述
现在桌子上有一堆飞行棋棋子,有 N
个,每个棋子上标有数字序号,现在想让你帮忙给这堆飞行棋分成 M
组,需要满足:
- 每个分组只能包含 5 个棋子
- 每个棋子只能出现在一个分组里
- 每个分组里的棋子的数字序号相同
请问可以完成上述分组么?
输入格式
空格分割的飞行棋棋子序号,如:1 3 4 5 6 5 4
输出格式
是否可以完成分组,如果可以输出 true
,否则输出 false
输入样例(1)
1 2 3 4 5
上述棋子只有 5 个只能分为一组,但组内棋子序号不一致,所以无法完成分组,输出 false
输出样例(2)
1 1 1 1 2 1 2 2 2 2
上述棋子可以分为两组,[1, 1, 1, 1, 1]
和 [2, 2, 2, 2, 2]
两组,可以完成分组,输出 true
数据范围
- 棋子数量:
1 <= N <= 10^5
- 棋子序号:
1 <= pieces[i] <= 40
解题思路:
问题理解
你需要将一堆飞行棋棋子分成若干组,每组包含5个棋子,并且每组中的棋子序号必须相同。问题的核心在于判断是否可以满足这些条件。
数据结构选择
- 计数器:我们可以使用一个计数器(如
std::map<int, int>
)来统计每个序号的棋子数量。 - 检查条件:在统计完所有棋子的数量后,我们需要检查每个序号的棋子数量是否是5的倍数。
算法步骤
- 输入处理:读取输入的棋子序号,并存储在一个数组或向量中。
- 统计数量:遍历棋子序号数组,使用
std::map<int, int>
统计每个序号的棋子数量。 - 检查分组条件:遍历
std::map
,检查每个序号的棋子数量是否是5的倍数。 - 返回结果:如果所有序号的棋子数量都是5的倍数,则返回
true
,否则返回false
。
最终代码:
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
std::string solution(std::vector<int> nums) {
// Please write your code here
if(nums.size() % 5 != 0){
return "False";
}
map<int,int> group;
for(auto i : nums){
group[i] ++;
}
for(map<int,int>::iterator it = group.begin();it !=group.end();it++){
if(it->second%5!=0)
return "False";
}
return "True";
}
int main() {
// You can add more test cases here
std::cout << (solution({1, 3, 4, 5, 6, 5, 4}) == "False") << std::endl;
std::cout << (solution({1, 1, 1, 1, 2, 1, 2, 2, 2, 2}) == "True") << std::endl;
std::cout << (solution({11, 45, 49, 37, 45, 38, 3, 47, 35, 49, 26, 16, 24, 4, 45, 39, 28, 26, 14, 22, 4, 49, 18, 4, 4, 26, 47, 14, 1, 21, 9, 26, 17, 12, 44, 28, 24, 24, 10, 31, 33, 32, 23, 41, 41, 19, 17, 24, 28, 46, 28, 4, 18, 23, 48, 45, 7, 21, 12, 40, 2, 19, 19, 28, 32, 6, 27, 43, 6, 18, 8, 27, 9, 6, 6, 31, 37, 15, 26, 20, 43, 3, 14, 40, 20}) == "False") << std::endl;
return 0;
}