剑指offer(PHP版改写)----数组部分

题目一:

  在一个长度为n的数组里的所有数字都在0~n-1的范围内。找出数组中任意一个重读数字。

/**
* 找出数组中的重复数字
* 长度为n的数组 所有数字在0~n-1的范围内
*
*
* @param $num 数组
* @param $length 数组长度
* @return bool
*/
function getNum($num,$length){
$mark = array();
if (count($num)==0||$length<=0){
return false;
}
for ($i=0;$i<$length;++$i){
if ($num[$i]<0||$num[$i]>$length-1){
return false;
}
}
for ($i=0;$i<$length;++$i){
while ($num[$i]!=$i){
if ($num[$i]==$num[$num[$i]]){
$mark[] = $num[$i];
break;
}
$temp = $num[$i];
$num[$i]=$num[$temp];
$num[$temp]=$temp;
}
}
return $mark;
}

$a = [3,2,4,6,5,2,3,6];
print_r(getNum($a,count($a)));
题目二:不修改数组找出重复数字
在一个长度为n+1的数组里所有数字都在1~n的范围内,所以必有重复数字。找出任意一个重复数字,但不能修改数组。
/**
* 不改变数组 找出任意一个重复数字
* 二分法
* 时间换空间
* @param $number 数组
* @param $length 数组长度
*/
function getDuplication($number,$length){

if (count($number)==0||$length<=0){
return false;
}

$start = 1;
$end = $length-1;

while($end>=$start){
$middle = (($end-$start)>>1)+$start; //位运算 求中值
$count =countRange($number,$length,$start,$middle) ;
if ($end==$start){
if ($count>1){
return $start;
}else{
break;
}
}

if ($count>($middle-$start+1)){
$end = $middle;
}else{
$start = $middle+1;
}

}

// return -1;
}

function countRange($num,$length,$start,$end){
if (count($num)==0){
return 0;
}

$count = 0;
for ($i = 0;$i<$length;$i++){
if ($num[$i]>=$start&&$num[$i]<=$end){
++$count;
}
}
return $count;
}

$a = [3,2,4,6,5,2,3,6];
print_r(getDuplication($a,count($a)));
posted @ 2019-07-19 11:54  来自德玛西亚的诺克萨斯  阅读(143)  评论(0编辑  收藏  举报