二分查找
1 必须是数组结构,实现查找o(1)。如果是用链表存储的,就无法在其上应用二分查找法了。
2 排序排序
时间复杂度:log(n)
二分查找的基本算法:
递归
array为排序数组
int binarysearch (int array[], int low, int high, int target)
{
if (low > high) return -1;
int mid =low+(high-low)/2;
if (array[mid]> target)
return binarysearch(array, low, mid -1, target);
if (array[mid]< target)
return binarysearch(array, mid+1, high, target);
//if (midValue == target)
return mid;
}
循环:
int binarysearch (int array[], int low, int high, int target)
{
while(low <= high)
{
int mid = (low + high)/2;
if (array[mid] > target)
high = mid - 1;
else if (array[mid] < target)
low = mid + 1;
else //find the target
return mid;
}
//the array does not contain the target
return -1;
}
二分查找法的缺陷
二分查找法的O(log n)让它成为十分高效的算法。不过它的缺陷却也是那么明显的。就在它的限定之上:必须有序,我们很难保证我们的数组都是有序的。当然可以在构建数组的时候进行排序,可是又落到了第二个瓶颈上:它必须是数组。数组读取效率是O(1),可是它的插入和删除某个元素的效率却是O(n)。因而导致构建有序数组变成低效的事情。
解决这些缺陷问题更好的方法应该是使用二叉查找树了,最好自然是自平衡二叉查找树了,自能高效的(O(nlogn))构建有序元素集合,又能如同二分查找法一样快速(O(log n))的搜寻目标数。插入、删除和查找算法的时间复杂度均为O(lgn)。
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有 下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
AVL平衡二叉树或为空树,或为如下性质的二叉排序树:
(1)左右子树深度之差的绝对值不超过1;
(2)左右子树仍然为平衡二叉树.
平衡因子BF=左子树深度-右子树深度.各项操作的时间复杂度:它的插入和删除某个元素的效率O(logN)
2.1.3 Search in Rotated Sorted Array
描述
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
2.1.4 Search in Rotated Sorted Array II
描述
Follow up for ”Search in Rotated Sorted Array”: What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
Write a function to determine if a given target is in the array.
//判读一个taregt是否存在有序数组中
考察二分法
**/*分析:
123456789—》6789 1 2345
当arr[begin]>arr[mid]
应该是6789 1 2345 后面肯定是升序 然后根据target目标来决定前面还是后面
当arr[begin]<arr[mid]
应该是 3456 7 8912 前面肯定是升序 然后根据target目标来决定前面还是后
*/****
function f7(&$arr,$target,$begin,$end)
{
if(false===is_array($arr)||empty($arr)) return -1;
if($end<$begin) return -1;
$mid=$begin+intval(($end-$begin)/2);
if($arr[$mid]==$target){
return $mid;
}
/*这是写错的
if($arr[$mid]>$target){
if($arr[$begin]>$target){
return f($arr,$target,$mid+1,$end);
}else{
return f($arr,$target,$begin,$mid-1);
}
}else{
if($arr[$end]>$target){
return f($arr,$target,$mid+1,$end);
}else{
return f($arr,$target,$begin,$mid-1);
}
}*/
if($arr[$begin]>$arr[$mid]){
if($target>$arr[$mid]&&$target<$arr[$end]){
return f7($arr,$target,$mid+1,$end);
}else{
return f7($arr,$target,$begin,$mid-1);
}
}else if($arr[$begin]<$arr[$mid]){
if($target<$arr[$mid]&&$target>$arr[$begin]){
return f7($arr,$target,$begin,$mid-1);
}else{
return f7($arr,$target,$mid+1,$end);
}
}else{//出现相同的时候
return f7($arr,$target,$begin+1,$end);
}
}
这个写错了
*function findSmall($arr,$begin,$end)
{
if(false===is_array($arr)) return false;
if($end<$begin) return ;
$n=$end-$begin;
if($n==0) return $arr[$begin];
if($n==1) return min($arr[$begin],$arr[$end]);
$mid=$begin+intval(($end-$begin)/2);
if($arr[$mid]>$arr[$begin]){
if($arr[$mid]>$arr[$end])
return findSmall($arr,$mid+1,$end);
else
return findSmall($arr,$begin,$mid-1);
}else{
return findSmall($arr,$mid,$end);错了
}
}
这种题,重点在于根据题意,缩小寻找的范围;
旋转数组的特点:根据判断中间mid和开头对应值的大小来判断前(后)段是升序。
123456789—》6789 1 2345
当arr[begin]<arr[mid]
应该是5678 9 1234 前面肯定是升序 ,最小的的肯定在后面。
但是要注意特例:
1234 5 6789 这时候最小的在前面尼。。。
反之 后面肯定是升序,但是最小在前面
例如7891 2 3456 最小在前面
function findSmall($arr,$begin,$end)
{
if (false === is_array($arr)) return false;
if ($end < $begin) return;
$n = $end - $begin;
if ($n == 0) return $arr[$begin];
if ($n == 1) return min($arr[$begin], $arr[$end]);
$mid = $begin + intval(($end - $begin) / 2);
/*
该题还要考虑是否存在相同的值
例如
11 1 01
这种情况只能采用顺序查找了。
*/
if ($arr[$mid] == $arr[$begin] && $arr[$mid] == $arr[$end])
return shunFind($arr,$begin,$end);
if ($arr[$mid] > $arr[$begin]){
if ($arr[$mid] < $arr[$end]){
return findSmall($arr, $begin, $mid);
}else
return findSmall($arr, $mid, $end);
}else
return findSmall($arr,$begin,$mid);
}
2 .1.5 Median of Two Sorted Arrays
描述
There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. the overall run time complexity should be O(log(m + n)).
这个题下标要想清楚~,很容易出错