青训营X 豆包MarsCode AI 刷题|叠盘子排序、分组飞行棋棋子

64 阅读6分钟

一、叠盘子排序

问题描述

小明是个讲究生活质量的人,家里的一切都井井有条,比如说家中的盘子都是一个系列,每个盘子都标有唯一的一个整数作为标识。在每次吃完饭后,小明都会将这些盘子按照特定的顺序叠放收拾起来,收拾的规则如下:

盘子叠放后会被分为多堆,每一堆都可能是由一个或多个盘子组成 叠放在同一堆的盘子的序号都是不间断递增的(例如 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 <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;
}

运行结果:

image.png

二、分组飞行棋棋子

问题描述

现在桌子上有一堆飞行棋棋子,有 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 <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;
}

运行结果:

image.png