<?php
/**
* 按分数对选手进行平均分组,可分多组。
*
*
* 注意:
* 1. 输入的选手名单players为集合形式,player表示选手名称,score表示选手的分数
* 2. 选手的分数体现选手的实力,分数有可能是负数
* 3. 最终解不是唯一,但要求分组后,每组的实力尽量接近,每组的人数也尽量接近
*
* 例如:
* 将所有选手,总共7人
* [
* {
* "player": "a",
* "score": 22
* },
* {
* "player": "b",
* "score": -9
* },
* {
* "player": "c",
* "score": 13
* },
* {
* "player": "d",
* "score": 17
* },
* {
* "player": "e",
* "score": 0
* },
* {
* "player": "f",
* "score": -11
* },
* {
* "player": "g",
* "score": -2
* }
* ]
* 分成两组,应该为4 vs 3的队形
* [
* [
* {
* "player": "a",
* "score": 22
* },
* {
* "player": "e",
* "score": 0
* },
* {
* "player": "g",
* "score": -2
* },
* {
* "player": "f",
* "score": -11
* }
* ],
* [
* {
* "player": "d",
* "score": 17
* },
* {
* "player": "c",
* "score": 13
* },
* {
* "player": "b",
* "score": -9
* }
* ]
* ]
* 分成3组,应该为3 vs 2 vs 2的队形
* [
* [
* {
* "player": "a",
* "score": 22
* },
* {
* "player": "b",
* "score": -9
* },
* {
* "player": "f",
* "score": -11
* }
* ],
* [
* {
* "player": "c",
* "score": 13
* },
* {
* "player": "e",
* "score": 0
* }
* ],
* [
* {
* "player": "d",
* "score": 17
* },
* {
* "player": "g",
* "score": -2
* }
* ]
* ]
*
*/
namespace Interview;
class AverageGroup
{
private $players = array();
private $count = 2;
/**
* @param [array] 选手名单
* @param [integer] 分组数
*/
function __construct($players, $count = 2) {
$this->players = $players;
$this->count = $count;
}
/**
* @return [array] 分组后的结果
*/
/*
* 思路:
* 元素替换法
* 默认把倒叙排列的数组分成两个数组,最大的$quantity个为一组,剩下最小的为另外一组,
* 依次用最小的里面的最大的元素替换最大的组里的最小的,然后对数组求和,
* 把和跟平均数比较,如果最大的数组的和小于等于平均数,就停止,返回最大的数组,
* 利用array_diff()得到另外一个数组。
*/
public function divide($group = array(),$count=2) {
$group_score = array();
//转换成只有score的一维数组
foreach ($group as $gro){
foreach ($gro as $k=>$v){
if($k=="score"){
array_push($group_score, $v);
}
}
}
$con = count($group_score);
$quantity = round($con/$count); //每组的人数
$sum = array_sum($group_score);
$average = round($sum/$count); // 分数取平均
rsort($group_score); //数组倒叙排列
$big_array = array();
for($a=0;$a<$quantity;$a++){
array_push($big_array, $group_score[$a]);
}
$small_array = array();
$small_array = array_diff($group_score, $big_array);
for($a=$con-$quantity;$a>=0;$a--){
if(array_sum($big_array)>$average){
for($b=$quantity;$b<$con;){
list($big_array[$a],$small_array[$b])=array($small_array[$b],$big_array[$a]);
if(array_sum($big_array)>$average){
$b++;
}else {
break;
}
}
}
}
//还原数组
$big = array();
$small = array();
foreach ($group as $gro){
foreach ($gro as $k=>$v){
if($k=="score"){
if(in_array($v, $big_array)){
$big []= $gro;
}else{
$small []= $gro;
}
}
}
}
print_r($big);
print_r($small);
}
}