二分查找算法原理
- 二分查找又叫折半查找,优点是查找速度快,平均性能好,算法时间的复杂度为O(logn);缺点是要求待查表为有序表,且插入删除困难,因此这种查找方法适用于不经常变动而查找频繁的有序列表。
- 二分查找算法如下:
- 输入:待查列表array,目标元素target
- 1、如果array为空,则返回-1,退出算法,-1表示查找不到target;
- 2、如果array不为空,则比较中间元素与target是否相等,如果相等,则返回该中间元素的索引,并退出算法;否则比较这俩元素的大小;
- 3、如果该中间元素大于target,那么target应该位于列表的前半部分,因此将列表前半部分作为待查找的列表;
- 4、如果该中间元素小于target,那么target应该位于列表的后半部分,因此将列表后半部分作为待查找的列表;
- 5、针对新的待查列表,重新从步骤1开始。
题1:二分查找
题目描述:请实现无重复数字的升序数组的二分查找。
示例:
输入:[-1,0,3,4,6,10,13,14],13
输出:6
代码实现
import java.util.*;
public class Solution {
public int search (int[] nums, int target) {
// 通过定义左右边界,定义待查找列表
int left = 0, right = nums.length-1;
int mid = (left+right)/2;
//当左边界大于右边界,终止
while(left<=right){
if(nums[mid] == target){
return mid;
}else if(nums[mid]>target){
right = mid-1;
}else{
left = mid+1;
}
mid = (left+right)/2;
}
return -1;
}
}
题2:二维数组中的查找
题目描述:在一个二维数组中,每一行递增排序,每一列递增排序,给定一个整数,判断该二维数组中是否含有该整数。
示例:
输入:7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
输出:true
代码实现
//可以利用二维数组行列递增特性,从二维数组右上角出发进行判断,如果大于目标元素,那么应该向左搜索寻找;
//如果小于目标元素,应该向下寻找
public class Solution {
public boolean Find(int target, int [][] array) {
int m = array.length;
int n = array[0].length;
int row = 0, col = n-1;
while(row<m && col>=0){
if(array[row][col]>target){
col -= 1;
} else if(array[row][col]<target){
row += 1;
} else{
return true;
}
}
return false;
}
}
题3:寻找峰值元素
题目描述:给定一个长度为n的数组,请找到峰值元素的索引并返回。峰值元素是指其值严格大于左右相邻值的元素,即不能等于。数组可能包含多个峰值,可任意返回一个位置即可。假设nums[-1] = nums[n] = 负无穷。
示例:
输入:[2,4,1,2,7,8,4]
输出:1(4和8都是峰值元素,返回索引1和索引5都可以)
代码实现
// 容易理解的一种方法:顺序遍历数组,并设置一个元素递增的检查标志,
//当下一个元素大于当前元素时,将标志置位true,并获得可能的峰值索引
// 当小于下一个元素时,表明开始出现下降,此时若递增标志为true,则表明遇到了峰值,跳出循环,返回峰值索引
public class Solution {
public int findPeakElement (int[] nums) {
boolean increase_checking = false;
int peek_index = 0;
for(int i=0;i<nums.length-1;i++){
if(nums[i] < nums[i+1]){
increase_checking = true;
peek_index = i+1;
}else if(nums[i]>nums[i+1] && increase_checking){
break;
}
}
return peek_index;
}
}
// 还有一种是采用二分查找,我觉得不容易理解
// 简单的解释:为找到一个局部的峰值,我们每次将搜索范围缩小一半,这一半确保了峰值的一个边界条件成立,而另一半是不成立的
// 但是,当最终减少到一个数字的时候,此时单个数的两个峰值边界条件都满足了
public class Solution {
public int findPeakElement (int[] nums) {
int left = 0,right = nums.length-1;
int mid = (left+right)/2;
while(left<right){
// 当大于下一个元素时,我们选择在左边查找
// 否则,在右边查找
if(nums[mid]>nums[mid+1]){
right = mid;
} else {
left = mid+1;
}
mid = (left+right)/2;
}
return left;
}
参考
https://www.jianshu.com/p/99257a99e6d5
如有侵权,请联系作者删除