二分查找法
- 一、标准二分查找法
- 二、改动版二分查找法
- 三、平衡版二分查找法
- 四、二分查找法查找最左元素
- 五、二分查找法查找最右元素
- 六、二分查找法之返会插入位置
一、标准二分查找法
/**
* 标准二分查找
*/
public static int binarySearch(int[] arr, int target) {
int i = 0, j = arr.length - 1; // 1.定义查找范围为左闭右闭
while (i <= j) {
int m = (i + j) >>> 1; // 2.无符号右移一位
if (arr[m] < target) {
i = m + 1; // 3.目标值大于中间值,所以在右范围查询
} else if (target < arr[m]) {
j = m - 1; // 4.目标值小于中间值,所以在左范围查询
} else {
return m; // 目标==中间值
}
}
return -1;
}
二、改动版二分查找法
/**
* 改动版二分查找
*/
public static int modifyBinarySearch(int[] arr, int target) {
int i = 0, j = arr.length; // 1.定义查找范围为左闭右开
while (i < j) {
int m = (i + j) >>> 1; // 2.无符号右移一位
if (arr[m] < target) {
i = m + 1; // 3.目标值大于中间值,所以在右范围查询
} else if (target < arr[m]) {
j = m; // 4.目标值小于中间值,所以在左范围查询(j作为右边界不参与比较,m本身已经比较过)
} else {
return m; // 目标==中间值
}
}
return -1;
}
三、平衡版二分查找法
/**
* 平衡版二分查找
*/
public static int BalanceBinarySearch(int[] arr, int target) {
int i = 0, j = arr.length; // 1.定义查找范围为左闭右开
while (1 < j - i) { // j和i至少有一个元素
int m = (i + j) >>> 1; // 2.无符号右移一位
if (arr[m] <= target) {
i = m; // 3.目标值大于中间值,所以在右范围查询
} else {
j = m; // 4.目标值小于中间值,所以在左范围查询(j作为右边界不参与比较,m本身已经比较过)
}
}
if (arr[i] == target) {
return i;
} else {
return -1;
}
}
四、二分查找法查找最左元素
/**
* 二分查找之查找最左
*/
public static int leftBinarySearch(int[] arr, int target) {
int i = 0, j = arr.length-1; // 1.定义查找范围为左闭右闭
int t = -1;
while (i <= j) {
int m = (i + j) >>> 1; // 2.无符号右移一位
if (arr[m] < target) {
i = m + 1; // 3.目标值大于中间值,所以在右范围查询
} else if (target < arr[m]) {
j = m - 1; // 4.目标值小于中间值,所以在左范围查询(j作为右边界不参与比较,m本身已经比较过)
} else {
t = m; // 目标==中间值
j = m -1;
}
}
return t;
}
五、二分查找法查找最右元素
/**
* 二分查找之查找最右
*/
public static int rightBinarySearch(int[] arr, int target) {
int i = 0, j = arr.length-1; // 1.定义查找范围为左闭右闭
int t = -1;
while (i <= j) {
int m = (i + j) >>> 1; // 2.无符号右移一位
if (arr[m] < target) {
i = m + 1; // 3.目标值大于中间值,所以在右范围查询
} else if (target < arr[m]) {
j = m - 1; // 4.目标值小于中间值,所以在左范围查询(j作为右边界不参与比较,m本身已经比较过)
} else {
t = m; // 目标==中间值
i = m + 1;
}
}
return t;
}
六、二分查找法之返会插入位置
/**
* 二分查找之查找最右
*/
public static int insertionBinarySearch(int[] arr, int target) {
int i = 0, j = arr.length-1; // 1.定义查找范围为左闭右闭
while (i <= j) {
int m = (i + j) >>> 1; // 2.无符号右移一位
if (arr[m] < target) {
i = m + 1; // 3.目标值大于中间值,所以在右范围查询
} else if (target <= arr[m]) {
j = m - 1; // 4.目标值小于中间值,所以在左范围查询(j作为右边界不参与比较,m本身已经比较过)
}
}
return i;
}
测试代码:
public static void main(String[] args) {
int[] nums = {1, 3, 6,6,6, 8, 12, 15, 23, 26, 31, 35};
/* 二分查找(双闭区间) */
int index = binarySearch(nums, 6);
System.out.println("目标元素 6 的索引 = " + index);
int index2 = binarySearch(nums, 5);
System.out.println("目标元素 5 的索引 = " + index2);
/* 二分查找(左闭右开区间) */
int index3 = modifyBinarySearch(nums, 6);
System.out.println("目标元素 6 的索引 = " + index3);
int index4 = modifyBinarySearch(nums, 5);
System.out.println("目标元素 5 的索引 = " + index4);
/* 平衡板二分查找 */
int index5 = BalanceBinarySearch(nums, 6);
System.out.println("目标元素 6 的索引 = " + index5);
int index6 = BalanceBinarySearch(nums, 5);
System.out.println("目标元素 5 的索引 = " + index6);
/* 平衡板二分查找 */
int index7 = leftBinarySearch(nums, 6);
System.out.println("目标元素 6 的索引 = " + index7);
int index8 = leftBinarySearch(nums, 5);
System.out.println("目标元素 5 的索引 = " + index8);
int index9 = rightBinarySearch(nums, 6);
System.out.println("目标元素 6 的索引 = " + index9);
int index10 = rightBinarySearch(nums, 5);
System.out.println("目标元素 5 的索引 = " + index10);
int index11 = insertionBinarySearch(nums, 6);
System.out.println("目标元素 6 的索引 = " + index11);
int index12 = insertionBinarySearch(nums, 5);
System.out.println("目标元素 5 的索引 = " + index12);
}
测试截图: