public class BinarySerach {
/**
* 二分查找
* 需求:在有序数组A内,查找值target
* 如果找到返回索引
* 如果找不到返回-1
*/
public static int binarySearchBasic(int[]a, int target) {
int i = 0;
int j = a.length - 1; // 设置指针和初始值
while (i <= j) {
// int m = (i + j) / 2;
int m = (i + j) >>> 1;
if(target < a[m]) {
j = m - 1;
} else if( a[m] < target){
i = m + 1;
} else {
return m;
}
}
return -1;
}
// 同一个二进制数
// 1011_1111_1111_1111_1111_1111_1111_1110
// 不把最高为视为符号位,代表3221225470
// 把最高为视为符号位,代表-1073741826
/**
*问题1: 为什么是 i<=j 意味着区间内有未比较的元素,而不是 i<j
* i==j 意味着 i,j 它们指向的元素也会参与比较
* 问题2:(i + j) / 2 有没有问题?
* 问题3:都写成小于号有啥好处?
*
* 针对 int m = (i + j) / 2 的优化: m = (i + j) >>> 1;
*/
/**
* 二分查找法改动版
* 需求:在有序数组A内,查找值target
* 如果找到返回索引
* 如果找不到返回-1
*/
public static int binarySearchAlternative(int[]a, int target) {
int i = 0;
int j = a.length;
while (i < j) {
int m = (i + j) >>> 1;
if(target < a[m]) {
j = m;
} else if( a[m] < target){
i = m + 1;
} else {
return m;
}
}
return -1;
}
/**
* 时间复杂度
*
* int m = (i+j)>>>1 执行
*
*
*/
/**
* 空间复杂度
*/
public static int binarySearchBalanceAlternative1(int[]a, int target) {
int i = 0;
int j = a.length;
while(1 < j - i) {
int m = (j + i) >>> 1;
if (target < a[m]) {
j = m;
} else {
i = m;
}
}
if (a[i] == target) {
return i;
}else{
return -1;
}
}
/**
* binarySearch java版
* int[] a = {2, 5, 8}
* int target = 4;
*
* [2, 5, 8]
* [2, 0, 0, 0] b
* [2, 4, 0, 0] b
* [2, 4, 5, 8] b
*
*
*/
public static int[] binarySearchJava(int[] a, int target) {
int i = Arrays.binarySearch(a, target);
System.out.println(i);
// -2 = -插入点(插入的index) - 1
// -2 + 1 = -插入点
if (i < 0) {
int insertIndex = Math.abs(i + 1);
int[] b = new int[a.length + 1];
System.arraycopy(a, 0, b, 0, insertIndex);
b[insertIndex] = target;
System.arraycopy(a, insertIndex, b, insertIndex + 1, a.length - insertIndex);
System.out.println(Arrays.toString(b));
return b;
}
return a;
}
/**
* 二分查找:重复元素 Leftmost
* 基于基础版
*
* Params: a -待查找的升序舒徐
* target - 待查找的目标值
* Returns:
* 找到则返回最靠左索引
* 找不到则返回 -1
*/
public static int binarySearchLeftmost1(int[] a, int target) {
int i = 0;
int j = a.length - 1;
int candidate = -1;
while (i <= j) {
int m = (i + j) >>> 1;
if (target < a[m]) {
j = m - 1;
} else if (a[m] < target) {
i = m + 1;
} else {
// 记录m指向的位置作为候选者
candidate = m;
j = m - 1;
}
}
return candidate;
}
/**
* 可以修改为
* i的含义:
* (1)找到的情况下返回的i就是最靠左的目标值的位置
* (2)找不到时返回的i就是大于目标值的最靠左数的位置
*
*/
public static int binarySearchLeftmost2(int[] a, int target) {
int i = 0;
int j = a.length - 1;
while (i <= j) {
int m = (i + j) >>> 1;
if (target <= a[m]) {
j = m - 1;
} else {
i = m + 1;
}
}
return i;
}
/**
* 二分查找:重复元素 Rightmost
* 基于基础版
*
* Params: a -待查找的升序舒徐
* target - 待查找的目标值
* Returns:
* 找到则返回最靠左索引
* 找不到则返回 -1
*/
public static int binarySearchRightmost1(int[] a, int target) {
int i = 0;
int j = a.length - 1;
int candidate = -1;
while (i <= j) {
int m = (i + j) >>> 1;
if (target < a[m]) {
j = m - 1;
} else if (a[m] < target) {
i = m + 1;
} else {
// 记录m指向的位置作为候选者
candidate = m;
i = m + 1;
}
}
return candidate;
}
/**
* 二分查找:重复元素 Rightmost
* 基于基础版
*
* 可以修改为
* i的含义:
* (1)找到的情况下返回的i就是最靠右的目标值的位置
* (2)找不到时返回的i就是小于目标值的最靠右数的位置
*
*/
public static int binarySearchRightmost2(int[] a, int target) {
int i = 0;
int j = a.length - 1;
while (i <= j) {
int m = (i + j) >>> 1;
if (target < a[m]) {
j = m - 1;
} else {
i = m + 1;
}
}
return i - 1;
}
}