diff --git a/php/16_binary/binary.php b/php/16_binary/binary.php new file mode 100644 index 00000000..fc27a4cb --- /dev/null +++ b/php/16_binary/binary.php @@ -0,0 +1,191 @@ + + */ +function findFirstEqual(array $numbers,$find) { + $length = count($numbers); + $low = 0; + $high = $length - 1; + while($low <= $high) { + $mid = $low + (($high-$low)>>1); + if($numbers[$mid] > $find) { + $high = $mid - 1; + }else if($numbers[$mid] < $find) { + $low = $mid + 1; + }else { + /** + * 如果是第一个元素,或之前一个元素不等于我们要找的值 + * 我们就找到了第一个=find的element + */ + if($mid==0 || $numbers[$mid-1]!=$find) { + return $mid; + }else { + $high = $mid - 1; + } + } + } + + return -1; +} + +/** + * 找到最后一个=find的元素 + * @param array $numbers + * @param [type] $find + * + * @return void + * @date 2018/11/27 + * @author yuanliandu + */ +function findLastEqual(array $numbers,$find) { + $length = count($numbers); + $low = 0; + $high = $length - 1; + while($low <= $high) { + $mid = $low + (($high-$low)>>1); + if($numbers[$mid] > $find) { + $high = $mid - 1; + }else if($numbers[$mid] < $find) { + $low = $mid + 1; + }else { + /** + * 如果mid是最后一个元素的index + * 或mid后一个元素!=我们要找的值 + * 则找到了最后一个=find的value + */ + if($mid==$length-1 || $numbers[$mid+1]!=$find) { + return $mid; + }else { + $low = $mid + 1; + } + } + } + + return -1; +} + +/** + * 找到第一个大于等于find的元素 + * @param array $numbers + * @param [type] $find + * + * @return void + * @date 2018/11/27 + * @author yuanliandu + */ +function findFirstGreaterEqual(array $numbers,$find) { + $length = count($numbers); + $low = 0; + $high = $length - 1; + while($low <= $high) { + $mid = $low + (($high-$low)>>1); + if($numbers[$mid] >= $find) { + if ($mid == 0 || $numbers[$mid-1] < $find) { + return $mid; + }else { + $high = $mid - 1; + } + }else { + $low = $mid + 1; + } + } + return -1; +} + +/** + * 找到最后一个小于等于find的元素 + * @param array $numbers + * @param [type] $find + * + * @return void + * @date 2018/11/27 + * @author yuanliandu + */ +function findLastLessEqual(array $numbers,$find) { + $length = count($numbers); + $low = 0; + $high = $length - 1; + while($low <= $high) { + $mid = $low + (($high-$low)>>1); + if($numbers[$mid] <= $find) { + if($mid==$length-1 || $numbers[$mid+1]> $find) { + return $mid; + } + $low = $mid + 1; + }else { + $high = $mid - 1; + } + } + return -1; +} + + + + + +/** + * 循环数组中找指定元素 + * @param array $numbers + * @param [type] $find + * + * @return void + * @date 2018/11/27 + * @author yuanliandu + */ +function searchCircularArray(array $numbers,$find) { + $length = count($numbers); + $low = 0; + $high = $length - 1; + + while($low <= $high) { + $mid = $low + (($high-$low)>>1); + if($numbers[$mid] === $find) { + return $mid; + } + + if($numbers[$low] > $numbers[$mid]) { + // 后半部分是有序数组 + if(($numbers[$mid] < $find) && ($numbers[$high] >= $find)) { + if($numbers[$high] === $find) return $high; + //在后半个区间内 + $low = $mid + 1; + }else { + $high = $mid - 1; + } + }else { + // 前半部分是有序的 + if(($numbers[$low] <= $find) && ($numbers[$mid] > $find)) { + // 在有序区间内 + if($numbers[$low] === $find) return $low; + $high = $mid - 1; + }else { + $low = $mid + 1; + } + } + + } + return -1; +} + +/*** + * 测试 + */ +$numbers = [1,2,3,3,3,4,5,6,8,11,13]; +$find = 3; + +var_dump(findFirstEqual($numbers,$find));//找到第一个等于find的元素 +var_dump(findFirstGreaterEqual($numbers,$find));//找到第一个大于等于find的元素 +var_dump(findLastEqual($numbers,$find));//找到最后一个=find的元素 +var_dump(findLastLessEqual($numbers,$find));//找到最后一个小于等于find的元素 + + +//测试在循环数组中找到指定数字 +$numbers = [9,10,1,2,3,4,5,6,7,8]; +$find = 2; +var_dump(searchCircularArray($numbers,$find));