输入:数组,所有值为非负整数
目标:通过变换使数组的每个值为所有值的平均值,并且迭代次数最少
变换方法:某个值自身减一,使其紧邻左边或紧邻右边的值加一。数组第一个值只能向右传递1,最后一个向左传递1. 变换过程中数组内所有值不可为负。
例1:
输入 : [0, 3, 3]
第一次: [1, 2, 3] [1, 3, 2]
第二次: [2, 2, 2]
例2
[2, 4, 6, 2, 1]
[3, 3, 5, 2, 2]
[3, 3, 4, 2, 3]
[3, 3, 3, 3, 3]
例3
[1, 0, 7, 0]
[1, 1, 6, 0]
[2, 1, 5, 0]
[2, 2, 4, 0]
[2, 2, 3, 1]
[2, 2, 2, 2]
这个问题有什么好的算法解决吗,例子不是唯一解。求思路,用php实现。
$ar = [0, 3, 3];
$ar = [2, 4, 6, 2, 1];
$ar = [1, 0, 7, 0];
$ar = [5, 5, 5, 5, 25];
do {
$loop = 0;
for($i=0; $i<count($ar) - 1; $i++) {
if($n = casecmp($ar[$i], $ar[$i+1])) {
$ar[$i] += $n;
$ar[$i+1] -= $n;
$loop++;
}
}
printf("[%s]\n", join(', ', $ar));
}while($loop);
function casecmp($a, $b) {
if($a == $b) return 0;
return $a > $b ? -1 : 1;
}
[1, 1, 6, 0]
[2, 1, 5, 0]
这是怎么来的,某个值自身减一,使其左边或右边的值加一,6减少1怎么加到第一个去的?
<?php
function printArray($array){
print "[";
foreach ($array as $key => $value)
$key==count($array)-1? print $value :print $value.", ";
print "]\n";
}
function balance($a,$averge){
while (1){
$count=0;
foreach ($a as $key => $value){
$key==0?$left=null:$left=$a[$key-1];
$key==count($a)-1?$right=null:$right=$a[$key+1];
$value=$a[$key];
if (is_null($left)&&$value>$averge) { $a[$key]--; $a[$key+1]++; continue;}
if (is_null($right)&&$value>$averge) { $a[$key]--; $a[$key-1]++; continue;}
if (!is_null($left)&&!is_null($right)&&$left<$averge&&$value!=0) { $a[$key]--; $a[$key-1]++;continue;}
if (!is_null($left)&&!is_null($right)&&$right<$averge&&$value!=0) { $a[$key]--; $a[$key+1]++;continue;}
$count++;
if($count==count($a)) return 0;
}
printArray($a);
}
}
if($argc<2) exit("php solution.php number1 number2 number3 ...\n");
array_shift($argv);
foreach ($argv as $number){
if(!preg_match("/^[1-9]\d*$|^0$/",$number))
exit("wrong number: $number\n");
}
$averge=array_sum($argv)/($argc-1);
if(!is_int($averge)) exit("numbers you input,can not be balance\n");
printArray($argv);
balance($argv,$averge);
?>
我用了模仿例子的方法,无论自身大小,只要左右两边的值小于平均值就传递,显而易见的是有许多重复传递,谁还有其他方法吗,多谢
[5, 5, 5, 5, 25]
[6, 5, 5, 5, 24] //除了第一个值,所有值都向左传递了1
[7, 5, 5, 5, 23]
[8, 5, 5, 5, 22]
[9, 5, 5, 5, 21]// [9, 5, 5, 5, 21] [9, 4, 6, 5, 21] [9, 5, 5, 5, 21] [9, 5, 6, 4, 21] [9, 5, 6, 5, 20] 冗余
[9, 5, 6, 5, 20]
[9, 5, 7, 5, 19]
[9, 5, 8, 5, 18]
[9, 5, 9, 5, 17]
[9, 6, 9, 5, 16]
[9, 7, 9, 5, 15]
[9, 8, 9, 5, 14]
[9, 9, 9, 5, 13]
[9, 9, 9, 6, 12]
[9, 9, 9, 7, 11]
[9, 9, 9, 8, 10]
[9, 9, 9, 9, 9]
求出均值,然后从数组首尾两段比较可以嘛?