什么是二分
数组必须有序。使用lo和hi两个变量,进入循环,不断将数组arr的中间键mid和key比较,如果标中,返回mid,否则将查找范围缩小一半,俗称二分
arr[mid]>key ===》target在数组左边
arr[mid]<key ===》target在数组右边
当数组无重复且有序
/*这个比较简单,如果 * point : * 1.int mid = (hi - lo) / 2 + lo; * 试想lo已经移动不为0,中间数肯定是(后-前)/2,但如果贸然(hi-lo)/2是会错误的, * 2.JAVA数组下标中间值是趋于左的,也就是说 1 2 3 4 mid=2而不是3(因为3/2=>1这个需要细讲,这里不影响) * */
//sorted & element not repeat
private static int search(int key, int[] arr) {
if (arr.length <= 0) {
return -1;
}
int lo = 0;
int hi = arr.length - 1;
while (lo <= hi) {
int mid = (hi - lo) / 2 + lo;
if (arr[mid] == key) {
return mid;
} else if (arr[mid] < key) {
lo = mid + 1;
} else if (arr[mid] > key) {
hi = mid - 1;
}
}
return -1;
}
对于重复key的
1、当我们要找到目标元素出现的第一个位置时候:当中间值大于等于目标元素的时候,往左边继续查找。
这句话用条件语句表述就是:
if(a[mid] >= key)
hi= mid;
2、当我们要找目标元素出现的最后一个位置的时候:当中间值小于等于目标元素的时候,往右边继续查找。
if(a[mid] <= key)
lo= mid;3、
lo右移 lo=mid+1
hi左移 hi= mid-1
对于mid值
是的,我们都知道mid的值,寻找第一个key的时候mid = (hi-lo)/2+lo没有问题,因为趋于左边,不会让while进入死循环,但是在寻找最后一个key的时候,如果偶数数组,lo右移,但是由于mid一直不变,lo一直不变,就会将进入死循环了,所以为了让mid在二分时趋于右边,mid=(hi-lo+1)/2+lo
数组有序有重复/查找第一个key
//sorted & element repeat & find the first position
private static int search2(int key, int[] arr) {
if (arr.length <= 0) {
return -1;
}
int lo = 0;
int hi = arr.length - 1;
while (lo < hi) {
int mid = (hi - lo) / 2 + lo;
if (arr[mid] >= key) {
hi = mid;
} else if (arr[mid] < key) {
lo = mid + 1;
}
}
return arr[lo] == key ? lo : -1;
}
数组有序有重复/查找最后一个key
//sorted & element repeat & find the last position
private static int search3(int key, int[] arr) {
if (arr.length <= 0) {
return -1;
}
int lo = 0;
int hi = arr.length - 1;
while (lo < hi) {
//让mid在二分的时候趋于右而不是左边,避免死循环
int mid = (hi - lo + 1) / 2 + lo;
if (arr[mid] <= key) {
lo = mid;
} else {
hi = mid - 1;
}
}
return arr[hi] == key ? hi : -1;
}
LeetCode34. Find First and Last Position of Element in Sorted Array
package Array.Medium;
/*
* Given an array of integers nums sorted in ascending order,
* find the starting and ending position of a given target value.
* Your algorithm's runtime complexity must be in the order of O(log n).
* If the target is not found in the array, return [-1, -1].
* Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
* */
import java.util.Arrays;
public class Yiki_34_FindFirstandLastPositionofElementinSortedArray {
private static int search2(int key, int[] arr) {
if (arr.length <= 0) {
return -1;
}
int lo = 0;
int hi = arr.length - 1;
while (lo < hi) {
int mid = (hi - lo) / 2 + lo;
if (arr[mid] >= key) {
hi = mid;
} else if (arr[mid] < key) {
lo = mid + 1;
}
}
return arr[lo] == key ? lo : -1;
}
//sorted & element repeat & find the last position
private static int search3(int key, int[] arr) {
if (arr.length <= 0) {
return -1;
}
int lo = 0;
int hi = arr.length - 1;
while (lo < hi) {
//让mid在二分的时候趋于右而不是左边,避免死循环
int mid = (hi - lo + 1) / 2 + lo;
if (arr[mid] <= key) {
lo = mid;
} else {
hi = mid - 1;
}
}
return arr[hi] == key ? hi : -1;
}
private static int[] searchRange(int[] nums, int target) {
int[] res = {-1, -1};
int first = search2(target, nums);
int last = search3(target, nums);
res[0] = first;
res[1] = last;
return res;
}
public static void main(String[] args) {
int[] nums = {5, 7, 7, 8, 8, 10};
int t1 = 8;
int t2 = 6;
System.out.println(Arrays.toString(searchRange(nums, t1)));
System.out.println(Arrays.toString(searchRange(nums, t2)));
}
}