字节青训-叠盘子排序、分组飞行棋棋子

目录

一、叠盘子排序

问题描述

输入格式

输出格式

解题思路:

问题理解

数据结构选择

算法步骤

最终代码:

运行结果:

二、分组飞行棋棋子

问题描述

输入格式

输出格式

数据范围

 解题思路:

问题理解

数据结构选择

算法步骤

最终代码:

 运行结果:


一、叠盘子排序

问题描述

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

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

解题思路:

问题理解

  1. 输入:一个整数序列,表示盘子的标识。
  2. 输出:一个字符串,表示盘子的叠放方式。
  3. 规则
    • 盘子需要被分成多个堆。
    • 每个堆中的盘子序号是不间断递增的,并且至少有3个盘子。
    • 如果堆中只有一个盘子,直接输出该盘子的序号。
    • 如果堆中有多个盘子,输出起始编号和终止编号,用“-”连接。

数据结构选择

  • 使用一个字符串来存储最终的输出结果。
  • 使用一个变量来记录当前堆的起始编号。
  • 使用一个变量来记录当前堆的终止编号。

算法步骤

  1. 初始化

    • 将第一个盘子的序号作为当前堆的起始编号。
    • 将第一个盘子的序号作为当前堆的终止编号。
  2. 遍历盘子序列

    • 如果当前盘子的序号是前一个盘子的序号加1,则更新当前堆的终止编号。
    • 如果当前盘子的序号不是前一个盘子的序号加1,则判断当前堆的长度:
      • 如果长度大于等于3,将当前堆的起始编号和终止编号加入结果字符串。
      • 如果长度小于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个棋子,并且每组中的棋子序号必须相同。问题的核心在于判断是否可以满足这些条件。

数据结构选择

  1. 计数器:我们可以使用一个计数器(如 std::map<int, int>)来统计每个序号的棋子数量。
  2. 检查条件:在统计完所有棋子的数量后,我们需要检查每个序号的棋子数量是否是5的倍数。

算法步骤

  1. 输入处理:读取输入的棋子序号,并存储在一个数组或向量中。
  2. 统计数量:遍历棋子序号数组,使用 std::map<int, int> 统计每个序号的棋子数量。
  3. 检查分组条件:遍历 std::map,检查每个序号的棋子数量是否是5的倍数。
  4. 返回结果:如果所有序号的棋子数量都是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;
}

 运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像污秽一样

谢谢谢谢谢谢谢谢谢谢谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值