N个人围成一环形圈,第一个人从1开始报数,报道M的人出列,直到最后一个同学

问题:N个人围成一环形圈,第一个人从1开始报数,报道M的人出列,直到最后一个同学并输出

分析:N个人保存在大小为N的数组中,索引为0的人员从1开始报数,每报道M的索引被清除,总共清除N-1次,数组最后大小为1既为所求

代码:

<?php
$n=10;//N个人
$m=3;//M值
$arr = array();
for($i=0;$i<$n;++$i){
    $arr[$i] = 1;
}
$i = $m-1;//第一个出局索引
echo get_last_index($arr, $i,$m, $n);

/**

 * 获取最后一个人员的数组索引
 * @params array $arr 标识人员的数组,初始为所有人员
 * @params int $i 第一个出局人员的索引
 * @params int $m 每隔开$m人员淘汰
 * @params int $n 人员总数

 * @return int 最后一个人员的数组索引
 */
function get_last_index(&$arr, $i,$m, $n){
    $c = $n;
    while((–$c)>0){
        //echo $i.”<br />”;
        unset($arr[$i]);
        $i=get_out_index($arr,$i,$m,$n);
    }
    $arr = array_keys($arr);
    return $arr[0];
}
/**

 * 获取报道为M的人员的数组索引
 * @params array $arr 标识人员的数组,初始为所有人员
 * @params int $i 第一个出局人员的索引
 * @params int $m 每隔开$m人员淘汰
 * @params int $n 人员总数

 * @return int 报道为M的人员的数组索引
 */
function get_out_index(&$arr,$i,$m,$n){
    while($m>0){
        $i = ($i+1)%$n;
        if(isset($arr[$i])){
            –$m;
        }
    }
    return $i;
}
?>

测试数据:

N=10,M=3则输出3

N=10,M=2则输出4

N=20,M=3则输出19

N=30,M=4则输出5

随便手工测试了几个数据,因为时间关系没有找到现成的数据测试所以只测试了少数数据,如果发现有疑问请拍砖!

点赞