青训营刷题-38

174 阅读4分钟

38 飞行棋分组

现在桌子上有一堆飞行棋棋子,有 N 个,每个棋子上标有数字序号。现在想让你帮忙给这堆飞行棋分成 M 组,需要满足:

  • 每个分组只能包含 5 个棋子
  • 每个棋子只能出现在一个分组里。
  • 每个分组里的棋子的数字序号相同

请问可以完成上述分组么?

输入描述

输入为一行或多行,所有的数字以空格分隔,例如:

复制代码
1 3 4 5 6 5 4

输出描述

输出一个字符串,表示是否可以完成分组:

  • 如果可以完成分组,输出 true
  • 否则,输出 false

注意:输出为小写字母 truefalse

示例

示例 1

输入

1 2 3 4 5

输出

false

说明

  • 盘子序号1, 2, 3, 4, 5

  • 分组尝试

    • 只能尝试将这 5 个盘子分为一组,但组内棋子的序号必须相同。
    • 盘子序号不一致,无法形成满足条件的分组。
  • 结论:无法完成分组,输出 false

示例 2

输入

1 1 1 1 2 1 2 2 2 2

输出

True

说明

  • 盘子序号1, 1, 1, 1, 2, 1, 2, 2, 2, 2

  • 分组过程

    • 盘子 1 出现了 5 次,可以分为一组 [1, 1, 1, 1, 1]
    • 盘子 2 出现了 5 次,可以分为一组 [2, 2, 2, 2, 2]
  • 结论:可以将所有盘子分为两组,每组 5 个棋子且序号相同,输出 true

示例 3

输入

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

说明

  • 盘子序号:众多不重复或部分重复的数字,无法将所有棋子分为每组 5 个且序号相同的组。
  • 结论:无法完成分组,输出 false

示例 4

输入

1

输出

False

说明

  • 盘子序号:只有一个盘子 1

  • 分组尝试

    • 需要每组恰好 5 个棋子,无法满足。
  • 结论:无法完成分组,输出 false

数据范围

  • 棋子数量:1 <= N <= 10^5
  • 棋子序号:1 <= pieces[i] <= 40

解题思路

本问题要求将一堆飞行棋棋子分组,每组恰好包含 5 个棋子,且组内棋子的序号相同。每个棋子只能属于一个组。需要判断是否可以完成这样的分组。

1. 统计每个序号的出现次数

首先,统计每个棋子序号出现的次数。由于每组必须恰好包含 5 个棋子,且序号相同,因此每个序号的总次数必须是 5 的倍数。

2. 判断每个序号的次数是否为 5 的倍数

遍历统计结果,检查每个序号的出现次数是否可以被 5 整除。如果所有序号的次数都是 5 的倍数,则可以完成分组;否则,无法完成分组。

3. 时间与空间复杂度

  • 时间复杂度O(N),其中 N 是棋子的数量。需要遍历一次所有棋子以统计次数。
  • 空间复杂度O(1),由于棋子序号范围固定(1 <= pieces[i] <= 40),可以使用固定大小的数组来存储次数。

4. 注意事项

  • 输入格式:输入是一个以空格分隔的字符串,需要转换为整数数组。

  • 边界条件

    • N < 5 时,直接无法完成分组。
    • N 不是 5 的倍数时,无法完成分组。
    • 处理棋子序号的范围和重复情况。

算法实现

import java.util.*;
public class Main {
    public static String solution(int[] nums) {
        // Please write your code here
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int num : nums) {
            // 如果序号已经在哈希表中,次数加 1
            if (countMap.containsKey(num)) {
                countMap.put(num, countMap.get(num) + 1);
            } else {
                // 否则,初始化为 1
                countMap.put(num, 1);
            }
        }
        // 遍历哈希表,判断每个序号的出现次数是否能被 5 整除
        for (int count : countMap.values()) {
            if (count % 5!= 0) {
                return "False";
            }
        }
        return "True";
    }

    public static void main(String[] args) {
        // You can add more test cases here
        System.out.println(solution(new int[]{1, 3, 4, 5, 6, 5, 4}).equals("False"));
        System.out.println(solution(new int[]{1, 1, 1, 1, 2, 1, 2, 2, 2, 2}).equals("True"));
        System.out.println(solution(new int[]{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}).equals("False"));
    }
}