
本文介绍如何用 php 计算书写一个整数所需的最少数字集合数,其中每个集合包含 0–9 各一个数字,且数字 6 和 9 可互换使用(视为同一物理卡片旋转所得)。
本文介绍如何用 php 计算书写一个整数所需的最少数字集合数,其中每个集合包含 0–9 各一个数字,且数字 6 和 9 可互换使用(视为同一物理卡片旋转所得)。
在数字资源受限的实际场景中(例如电子价签、LED 数码管备件管理或趣味编程题),常需判断“写一个给定数字至少需要多少套 0–9 的完整数字卡片”。关键约束在于:每套卡片仅含 0–9 各一张;而数字 6 和 9 可通过旋转共用同一张卡片——即一张卡片既可作 6 也可作 9,因此它们共享计数配额。
核心思路是:统计目标数字中各字符的出现频次,将 9 统一归并为 6,再对 6 的总频次向上取整除以 2(因一张卡片可服务一个 6 或一个 9),最后取所有数字所需卡片数的最大值——即为答案。这是因为限制性最强的数字(出现最多次的那个)决定了整体所需集合数。
以下是完整、健壮的实现代码:
<?php
function countSet($input): int {
// 输入标准化:确保为字符串,兼容整数、字符串甚至带符号输入
$str = trim((string) $input);
if ($str === '' || !ctype_digit(ltrim($str, '-'))) {
throw new InvalidArgumentException("Input must be a non-empty numeric string");
}
// 替换所有 '9' 为 '6',统一处理共用卡片逻辑
$normalized = str_replace('9', '6', $str);
// 拆分为字符数组并统计频次
$chars = str_split($normalized);
$counts = array_count_values($chars);
// 特殊处理:'6' 实际代表 '6' 和 '9',一张卡片可服务二者之一
if (isset($counts['6'])) {
$counts['6'] = (int) ceil($counts['6'] / 2.0);
}
// 所有数字中最大频次即为最少所需集合数(瓶颈决定整体)
return (int) max($counts);
}
// 使用示例
echo countSet(10) . "\n"; // 输出: 1('1','0' 各1次,无冲突)
echo countSet(300) . "\n"; // 输出: 2('0' 出现2次 → 需2套)
echo countSet(266) . "\n"; // 输出: 1('2','6','6' → '6'频次2 → ceil(2/2)=1)
echo countSet(369) . "\n"; // 输出: 1('3','6','9' → 归并为 '3','6','6' → ceil(2/2)=1)
echo countSet(5666) . "\n"; // 输出: 2('5','6','6','6' → '6'频次3 → ceil(3/2)=2)
?>✅ 关键说明与注意事项:
立即学习“PHP免费学习笔记(深入)”;
- 输入鲁棒性:函数主动校验输入是否为有效数字字符串,避免空值或非法字符导致 array_count_values() 异常;
- 6/9 合并逻辑:str_replace('9','6',...) 确保所有 9 被计入 6 的计数,再通过 ceil($count/2) 精确反映“一张卡片服务两个形态”的本质;
- 结果语义明确:返回值即最小集合数,无需额外推导——例如 countSet(5666) 返回 2,表示至少需两套 0–9 卡片才能写出该数字;
- 性能友好:时间复杂度 O(n),n 为数字位数;空间复杂度 O(1)(频次数组最多10项);
- 扩展提示:若需支持前导零(如 "007")或负号(如 "-42"),应在预处理阶段按业务需求过滤非数字字符(如 preg_replace('/\D/', '', $str))。
该方案简洁、高效且符合现实约束,可直接集成至数字资源规划、编程竞赛或教学案例中。











