#二分查找——采用半开区间[i,j) publicstaticintbinarySearch(int[] a, int target) { int i = 0, j = a.length; while (i < j) { int m = (i + j) >>> 1; if (target < a[m]) j = m; elseif (target > a[m]) i = m + 1; elsereturn m; } return-1; }
1 2 3 4 5 6 7 8 9 10 11 12
#二分查找——采用闭区间[i,j] publicstaticintbinarySearch(int[] a, int target) { int i = 0, j = a.length - 1; while (i <= j) { int m = (i + j) >>> 1; if (target < a[m]) j = m - 1; elseif (a[m] < target) i = m + 1; elsereturn m; } return-1; }
基本的二分查找有以上两种方法,个人常用第一种方法。
接下来稍微变化一下二分查找,使其能够解决别的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#二分查找查找最左侧重复元素 #把中间索引移动到重复位置的最左侧,直到指向非目标数 publicstaticintLeftmost(int[] a, int target) { int i = 0, j = a.length - 1, candidate = -1; while (i <= j) { int m = (i + j) >>> 1; if (target < a[m]) j = m - 1; elseif (a[m] < target) i = m + 1; else { //记录候选位置 candidate = m; //因为查找最左侧元素,所以右边索引向左靠拢 j = m - 1; } } return candidate; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#二分查找查找最右侧重复元素 #把中间索引移动到重复位置的最右侧,直到指向非目标数 publicstaticintRightmost(int[] a, int target) { int i = 0, j = a.length - 1, candidate = -1; while (i <= j) { int m = (i + j) >>> 1; if (target < a[m]) j = m - 1; elseif (a[m] < target) i = m + 1; else { //记录候选位置 candidate = m; //因为查找最右侧元素,所以左边索引向右靠拢 i = m + 1; } } return candidate; }
以上两种可以进行简化
1 2 3 4 5 6 7 8 9 10 11 12
# 二分查找查找最左侧重复元素 # 返回值:返回的为大于等于目标最靠左侧的索引 publicstaticintLeftmost2(int[] a, int target) { int i = 0, 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 2 3 4 5 6 7 8 9 10 11 12
# 二分查找查找最右侧重复元素 # 返回值:返回的为小于等于目标最靠右侧的索引,不一定需要查找到目标元素 publicstaticintRightmost2(int[] a, int target) { int i = 0, 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; }