二分查找
总结:
1. 当要查找第一次出现的数(最左),mid下取整;
2. 当要查找最后一次出现的数(最右),mid上取整;
相关算法1:找一个数,如果有,返回任意一个(返回true),否则返回false
/**
* 找一个数,如果有,返回任意一个(返回true),否则返回false
* @param data
* @param k
*/
public static boolean BinarySearch1(int[] data, int k) {
// TODO Auto-generated method stub
int l = 0, r = data.length - 1;
while(l <= r)
{
int mid = l + (r - l) / 2; //下取整
if(data[mid] == k){
//return k;
return true;
}else if(data[mid] > k){
r = mid - 1;
}else {
l = mid + 1;
}
}
return false;
}
相关算法2: (leetcode之first bad version) k第一次出现的位置
public static int FirstBadVersion(int n){
int start = 1;
int end = n;
while(start < end){
int mid = start + (end -start) / 2;
if(!isBadVersion(mid)) start = mid + 1;
else end = mid;
}
return start;
}
相关算法3:k最后一次出现的位置,没有返回-1
/**
* k最后一次出现的位置,没有返回-1
* @param data
* @param k
* @return
*/
private static int BinarySearch2(int[] data, int k) {
// TODO Auto-generated method stub
int l = 0, r = data.length - 1;
while(l < r){
int mid = l + (r - l + 1) / 2; //上取整,否则会死循环
if(data[mid] == k)
{
l = mid;
}else if(data[mid] > k){
r = mid - 1;
}else{
l = mid + 1;
}
}
if(l == r && data[l] == k){
return l;
}else{
return -1;
}
}
相关算法4:查找小于k的最大的数
/**
* 查找小于k的最大的数
* @param data
* @param k
* @return
*/
private static int BinarySearch3(int[] data, int k) {
// TODO Auto-generated method stub
int l = 0, r = data.length - 1;
while(l < r){
int mid = l + (r - l + 1) / 2; //{k,k}用两个数来判断,不加1的话(mid = l & l = mid)会死循环
if(data[mid] >= k)
{
r = mid - 1;
}else {
l = mid;
}
}
if(l == r && data[l] < k){
return l;
}else{
return -1;
}
}
相关算法5:统计一个数字在排序数组中出现的次数—k最后一次出现的(算法2)-k第一次出现 (算法3)+ 1
public int GetNumberOfK(int [] array , int k) {
if(array == null || array.length <= 0)
return 0;
int first = getFirstK(array, k);
int last = getLastK(array, k);
if(first > -1 && last > -1)
return last - first + 1;
else
return 0;
}
//找k第一次出现的下标
public int getFirstK(int [] nums, int k){
int begin = 0, end = nums.length - 1;
while(begin < end){
int mid = begin + (end - begin) / 2; //下取整
if(nums[mid] == k)
end = mid;
else if(nums[mid] > k)
end = mid - 1;
else
begin = mid + 1;
}
if(nums[begin] == k)
return begin;
else
return -1; //没找到
}
//找最后一次出现的下标
public int getLastK(int [] nums, int k){
int begin = 0, end = nums.length - 1;
while(begin < end){
int mid = begin + (end - begin + 1) / 2;//上取整,否则会死循环
if(nums[mid] == k)
begin = mid;
else if(nums[mid] < k)
begin = mid + 1;
else
end = mid - 1;
}
if(nums[end] == k)
return end;
else
return -1;
}