题意是这样的:求解一个数组中元素a和b,其和sum=a+b,sum最接近num的数两个。array是一个整型数组。
其求解方式如下:
//求解数组中元素a和b,其和sum=a+b,sum最接近num的数两个。
//求解思想是:对数组进行顺序排序,然后对数组中的每个数遍历每个数能求得一个最优值,然后对每对值大小sum与给出的这个数num做比较,找出绝对值相差最小的那个数。
//以下程序是对以上的一个简单变化,其比较的是两个值sum-num的绝对值大小,找到绝对值最小的值。
//这个过程就是流水式的,在一次流水式的比较和判定过程就能确定下来,将对应的值存储在变量中,这里是c_1和c_2。
//这里还有带说明的是,在固定一个值查找另外一个值时,我使用的是$tmp=$num - $array[$i]查出与该数最接近的数,并返回其下标,获取对应的值最终就可以得到最小的最优值。
//只要该最优值最小,就可以确定该组数值。
$array = [5,67,56,32,16,19];
//$c_1,$c_2是存放找到的两个数值。
$c_1 = 0;
$c_2 = 0;
//最优值,在这里其
$opt = 0;
//输入的数
$num = 33;
//开始:
//分两步
//1.先排序
//2.判定
//3.查找
sort($array);
//依次遍历数组中的数其每个值的最优值
$length = count($array);
//数组元素个数大于2个
if($length < 2) exit("error array length");
//判断端数值
if($num <= ($array[0] + $array[0])){
$c_1 = $array[0];
$c_2 = $array[1];
}
else if($num >= ($array[$length - 1]+$array[$length-1]))
{
$c_1 = $array[$length-1];
$c_2 = $array[$length-2];
}
else {
//初始化最优值
$opt = $array[0] + $array[$length - 1] - $num;
if($opt < 0) $opt = -$opt;
for($i=0;$i<$length;$i++)
{
//获取相对的num跟接近的数。
$tmp = $num - $array[$i];
if($tmp <= 0) $tmp = -$tmp;
$node = search($i,$tmp, $array);
//当前查找的最优值的记录
$opt2 = $node + $array[$i] - $num;
//取其绝对值,也可用abs()取绝对值$opt2 = abs($opt2);
if( $opt2 < 0) $opt2 = -$opt2;
//判定做比较,找出最小的绝对值,并将其赋值给$c_1和$c_2
if($opt2 < $opt) {
$opt = $opt2;
$c_1 = $array[$i];
$c_2 = $node;
}
}
}
print_r($array);
echo "find ".$num." in array,".$c_1." and ".$c_2." sub more close";
//给定一个值求出和它最接近的数
//采用折半查找,查找该元素数值
function search($key,$num, $array)
{
//lft,$right左右折半下标指针
$left = 0;
unset($array[$key]);
//$tmpKeys = array_keys($array);
$array = array_merge($array,[]);
$right = count($array) - 1;
//中间指针
$half = floor(($left + $right) / 2);
//current为当前指针
$current = $left;
//跳出循环的标志符号,其只要在最后一轮,能判定已经是相邻的两个数,就能结束循环了。
$next = 0;
while($left <= $right)
{
$half = floor(($left + $right) / 2);
$next = $right - $left;
if($num == $array[$half])
{
$current = $half;
break;
}
elseif ($num > $array[$half]) {
$left = $half;
}
以上是找一个数组中任意两个数的和最接近,但这也只是记录单对数字,其实要优化也可以将其他多对相关的数字记录下来。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
为了search()返回以前下标,并非数字结果,我们可以这样做。
//求解数组中元素a和b,其和sum=a+b,sum最接近num的数两个。
//求解思想是:对数组进行顺序排序,然后对数组中的每个数遍历每个数能求得一个最优值,然后对每对值大小sum与给出的这个数num做比较,找出绝对值相差最小的那个数。
//以下程序是对以上的一个简单变化,其比较的是两个值sum-num的绝对值大小,找到绝对值最小的值。
//这个过程就是流水式的,在一次流水式的比较和判定过程就能确定下来,将对应的值存储在变量中,这里是c_1和c_2。
//这里还有带说明的是,在固定一个值查找另外一个值时,我使用的是$tmp=$num - $array[$i]查出与该数最接近的数,并返回其下标,获取对应的值最终就可以得到最小的最优值。
//只要该最优值最小,就可以确定该组数值。
$array = [5,12,34];
//$c_1,$c_2是存放找到的两个数值。
$c_1 = 0;
$c_2 = 0;
//最优值,在这里其
$opt = 0;
//输入的数
$num = 33;
//开始:
//分两步
//1.先排序
//2.判定
//3.查找
sort($array);
//依次遍历数组中的数其每个值的最优值
$length = count($array);
//数组元素个数大于2个
if($length < 2) exit("error array length");
//判断端数值
if($num <= ($array[0] + $array[0])){
$c_1 = $array[0];
$c_2 = $array[1];
}
else if($num >= ($array[$length - 1]+$array[$length-1]))
{
$c_1 = $array[$length-1];
$c_2 = $array[$length-2];
}
else {
//初始化最优值
$opt = $array[0] + $array[$length - 1] - $num;
if($opt < 0) $opt = -$opt;
for($i=0;$i<$length;$i++)
{
//获取相对的num跟接近的数。
$tmp = $num - $array[$i];
if($tmp <= 0) $tmp = -$tmp;
$node = search($i,$tmp, $array);
echo $node."\n";
//当前查找的最优值的记录
$opt2 = $array[$node] + $array[$i] - $num;
//取其绝对值,也可用abs()取绝对值$opt2 = abs($opt2);
if( $opt2 < 0) $opt2 = -$opt2;
//判定做比较,找出最小的绝对值,并将其赋值给$c_1和$c_2
if($opt2 <= $opt) {
$opt = $opt2;
$c_1 = $array[$i];
$c_2 = $array[$node];
}
}
}
print_r($array);
echo "find ".$num." in array,".$c_1." and ".$c_2." sub more close";
//给定一个值求出和它最接近的数
//采用折半查找,查找该元素数值
function search($key,$num, $array)
{
//lft,$right左右折半下标指针
$left = 0;
unset($array[$key]);
$tmpArray = [];
$j = 0;
foreach($array as $k => $v){
$tmpArray[$j]['key'] = $k;
$tmpArray[$j]['val'] = $v;
$j++;
}
$right = count($tmpArray) - 1;
//中间指针
$half = floor(($left + $right) / 2);
//current为当前指针
$current = $left;
//跳出循环的标志符号,其只要在最后一轮,能判定已经是相邻的两个数,就能结束循环了。
$next = 0;
while($left <= $right)
{
$half = floor(($left + $right) / 2);
$next = $right - $left;
if($num == $tmpArray[$half]['val'])
{
$current = $half;
break;
}
elseif ($num > $tmpArray[$half]['val']) {
$left = $half;
}
elseif($num < $tmpArray[$half]['val']) {
$right = $half;
}
if(($num - $tmpArray[$left]['val']) <= ($tmpArray[$right]['val'] - $num)){
$current = $left;
}
else{
$current = $right;
}
if($next <= 1) break;
}
return $tmpArray[$current]['key'];
}