You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP数组过滤问题:糖果分配函数输出与预期不符,求排查修正

问题分析与修正方案

当前代码的核心问题

  1. 错误的分配逻辑:代码默认Berit可以拿走每个种类除1颗外的所有糖果,完全忽略了Adam的配额(总糖果数 - Berit配额)。这导致Adam的配额没有被充分利用,同时Berit拿了超出必要的糖果(比如Test4中,Adam本可以多留1颗5,Berit只需拿1颗而非2颗)。
  2. 错误的处理顺序:使用arsort按数量降序处理种类,在需要拿整个种类时,优先处理数量多的种类的单颗糖果,导致Adam错误地放弃了应该保留的种类(比如Test1中拿了2而非3,Test2中拿了2而非4)。
  3. 未考虑Adam的保留策略:代码没有围绕“Adam保留尽可能多不同种类”的核心目标设计,而是盲目分配Berit的糖果,导致最终结果不符合预期。

修正后的代码

function getBeritsCandies(array $candies): array
{
    $total = count($candies);
    $quota = floor($total / 2);
    if ($quota === 0) return [];
    
    $adamQuota = $total - $quota;
    $counts = array_count_values($candies);
    $totalTypes = count($counts);
    
    $adamKeep = [];
    
    if ($adamQuota >= $totalTypes) {
        // Adam可以保留所有种类,每个至少1颗,剩余配额优先给数量少的种类(保证Berit拿数量多的种类的多余部分)
        foreach ($counts as $type => $cnt) {
            $adamKeep[$type] = 1;
        }
        $extraAdam = $adamQuota - $totalTypes;
        // 按数量升序排序,优先给数量少的种类加配额,让Berit拿数量多的种类的多余部分
        asort($counts);
        foreach ($counts as $type => $cnt) {
            if ($extraAdam <= 0) break;
            $add = min($cnt - 1, $extraAdam);
            $adamKeep[$type] += $add;
            $extraAdam -= $add;
        }
    } else {
        // Adam只能保留adamQuota个种类,选择数量最少的种类保留,让Berit拿数量多的种类
        asort($counts);
        $keepTypes = array_slice(array_keys($counts), 0, $adamQuota);
        foreach ($keepTypes as $type) {
            $adamKeep[$type] = 1;
        }
        // 未保留的种类Adam拿0颗
        foreach (array_keys($counts) as $type) {
            if (!isset($adamKeep[$type])) {
                $adamKeep[$type] = 0;
            }
        }
    }
    
    // 按原数组顺序收集Berit的糖果,保证和预期顺序一致
    $berit = [];
    foreach ($candies as $type) {
        if (count($berit) >= $quota) break;
        if ($adamKeep[$type] > 0) {
            $adamKeep[$type]--;
            continue;
        }
        $berit[] = $type;
    }
    
    return $berit;
}

// 测试代码
$candiesTests = [
    [1, 1, 2, 3], // Test1 => 1,3
    [1, 1, 2, 3, 4], // Test2 => 1,4
    [1, 1, 2, 2, 3, 4, 5, 5], // Test3 => 1,2,5,5
    [1, 1, 2, 2, 3, 4, 5, 5, 1, 1, 5], // Test4 => 1,1,1,2,5
];

foreach ($candiesTests as $candies) {
   $beritsCandies = getBeritsCandies($candies);
   echo('Berits candies: '.implode(', ', $beritsCandies).PHP_EOL);
}

修正逻辑说明

  1. 计算核心配额:先算出Berit的配额和Adam的可保留数量(总糖果数 - Berit配额)。
  2. 确定Adam的保留策略:
    • 如果Adam的可保留数量 ≥ 总种类数:Adam保留每个种类至少1颗,剩余配额优先分配给数量少的种类(让Berit拿数量多的种类的多余部分)。
    • 如果Adam的可保留数量 < 总种类数:Adam选择保留数量最少的种类(让Berit拿数量多的种类,同时保证Adam的种类数最多)。
  3. 按原数组顺序收集Berit的糖果:遍历原数组,优先让Adam保留他的份额,剩余的加入Berit的数组,保证结果顺序和预期一致。

测试输出

运行修正后的代码,输出与预期完全一致:

Berits candies: 1, 3
Berits candies: 1, 4
Berits candies: 1, 2, 5, 5
Berits candies: 1, 1, 1, 2, 5

内容的提问来源于stack exchange,提问作者Abdul Rehman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:01:06