分治算法--二分查找
分治算法的基本思想
- 分:把问题划分成子问题
- 治:递归的求解子问题
- 合:把子问题的解合并成问题的解
二分查找基本概念
在计算机科学中,二分查找又称为折半搜索,二分搜索,是一种在有序数组中查找某一特定元素的算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
时间复杂度:O(lgN),折半搜索每次都把搜索区域减少一半。
空间复杂度:O(1)。
分治步骤
- 分:验证中间元素
- 治:递归查询一个子串
- 合:Trivial
C语言实现
1.递归实现
int binary_search_in_recursion(const int arr[], int left, int right, int target)
{
if (left > right)
return -1;
int mid = (left + right) / 2;
if (target == arr[mid])
return mid;
else if (target < arr[mid])
return binary_search_in_recursion(arr, left, right - 1, target);
else
return binary_search_in_recursion(arr, left + 1, right, target);
}
2.非递归实现
int binary_search_not_recursion(const int arr[], int left, int right, int target)
{
while (left <= right)
{
int mid = (left + right) / 2;
if (target == arr[mid])
return mid;
else if (target > arr[mid])
left = mid + 1;
else
right = mid - 1;
}
return -1;
}
3.旋转过后的排序数组的二分查找
int binary_search_for_rotated_array(const int arr[], int left, int right, int target)
{
while (left <= right)
{
int mid = (left + right) / 2;
if (target == arr[mid])
return mid;
if (target < arr[mid])
{
if (arr[mid] < arr[right]) // target < arr[mid] < arr[right]
right = mid - 1;
else
{
if (target < arr[left]) // target < arr[left] < arr[mid]
left = mid + 1;
else // target > arr[left] && target < arr[mid]
right = mid - 1;
}
}
else
{
if (arr[left] < arr[mid]) // arr[left] < arr[mid] < target
left = mid + 1;
else
{
if (arr[right] < target) // arr[mid] < arr[right] < target
right = mid - 1;
else
left = mid + 1; // target > arr[mid] && target < arr[right]
}
}
}
return -1;
}
参考
【1】:http://zh.wikipedia.org/wiki/%E6%8A%98%E5%8D%8A%E6%90%9C%E7%B4%A2%E7%AE%97%E6%B3%95
【2】:http://www.cnblogs.com/ider/archive/2012/04/01/binary_search.html
【3】:http://xpgc.vicp.net/course/ada4ia09/TechDoc/ch02/ia-02-02-divide-and-comquer.pdf