数据结构之二分查找
Posted 小杰IT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之二分查找相关的知识,希望对你有一定的参考价值。
二分查找针对的是一个有序的数据集合,查找思想有点类似分治思想。每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。
二分查找是一种非常高效的查找算法,时间复杂度为O(logn)
二分查找代码递归实现:
public int BinarySearch(int[] arr, int i, int start, int end) {
int mid;
while (start <= end) {
mid = (start + end) / 2;
if (arr[mid] == i) {
return mid + 1;
} else if (arr[mid] < i) {
return fun(arr, i, mid + 1, end);
} else {
return fun(arr, i, start, mid - 1);
}
}
return -1;
}
二分查找代码非递归实现:
public int BinarySearch (int[] arr, int i) {
int start = 0;
int end = arr.length - 1;
int mid;
while (start <= end) {
mid = (start + end) / 2;
if (arr[mid] == i) {
return mid + 1;
} else if (arr[mid] < i) {
start = mid + 1;
} else {
end = mid - 1;
}
}
return -1;
}
这只是二分查找中最简单的一种情况,在不存在重复元素的有序数组中,查找值等于给定值的元素。最简单的二分查找不难,但是,二分查找的变形问题就比较难了。
变体一:查找第一个值等于给定值的元素
代码实现:
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
if ((mid == 0) || (a[mid - 1] != value))
return mid;
else
high = mid - 1;
}
}
return -1;
}
a[mid] 跟要查找的 value 的大小关系有三种情况:大于、小
于、等于。如果我们查找的是任意一个值等于给定值的元素,当 a[mid] 等于要查找的值时,a[mid]就是我们要找的元素。但是,如果我们求解的是第一个值等于给定值的元素,当 a[mid]等于要查找的值时,我们就需要确认一下这个 a[mid] 是不是第一个值等于给定值的元素。
如果 mid 等于 0,那这个元素已经是数组的第一个元素,那它肯定是我们要找的;如果 mid 不等于 0,但 a[mid] 的前一个元素 a[mid-1] 不等于value,那也说明 a[mid] 就是我们要找的第一个值等于给定值的元素。
如果经过检查之后发现 a[mid] 前面的一个元素 a[mid-1] 也等于 value,那说明此时的a[mid] 肯定不是我们要查找的第一个值等于给定值的元素。那我们就更新 high=mid-1,因为要找的元素肯定出现在 [low, mid-1] 之间。
变体二:查找最后一个值等于给定值的元素
代码实现:
public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
if ((mid == arr.length-1) || (a[mid + 1] != value))
return mid;
else
high = mid - 1;
}
}
return -1;
}
变体三:查找第一个大于等于给定值的元素
public int binarySearch(int[] arr, int value) {
int low=0;
int high=arr.length-1;
while(low<=high){
int mid=low +((high-low)/2);
if(arr[mid]>=value){
if(mid==0||(arr[mid-1]<value)){
return mid;
}else{
high=mid-1;
}
}else{
low=mid+1;
}
}
return -1;
}
变体四:查找最后一个小于等于给定值的元素
private static int binarySearch(int[] arr, int value) {
int low=0;
int high=arr.length-1;
while(low<=high){
int mid=low +((high-low)/2);
if(arr[mid]<=value){
if(mid==arr.length-1||(arr[mid+1]>value)){
return mid;
}else{
low=mid+1;
}
}else{
high=mid-1;
}
}
return -1;
}
以上是关于数据结构之二分查找的主要内容,如果未能解决你的问题,请参考以下文章