赞
踩
这是最常规的一种查找,给定一个元素key, 如果key存在于数组中,返回key对应的下标,不存在则返回-1
[0,1,2,3,4,5,6,]
: 如果key=1,查找结果返回1;key=7,查找结果返回-1
left=0,right=n-1
n表示数组的长度
public static int binary_search(int nums[], int target) {
if (nums == null || nums.length == 0)
return -1;
int left = 0, right = nums.length-1;
while (left <= right) {//注意点1
int mid = left + (right - left) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid-1;//注意点2
}
return -1;
}
left=0,right=n
n表示数组的长度
public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length; while (left < right) {//注意点1 int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid;//注意点2 } return -1; }
两种情况对比:
左闭右闭:
注意点1: 因为right的取值是nums.length-1
,因此while循环处需要使用<=号,此时当left==right==nums.length-1
时,循环体中下标并不会越界;
注意点2:因为时左闭右闭区间,因此当mid被访问之后,当访问mid左边的元素时应该是[left.mid-1], 由于是左闭右闭区间,所以直接right=mid-1
左闭右开:
注意点1:因为right的取值是nums.length
,因此while循环处需要使用<号,而不是<=, 因为当left==right==nums.length
;时,循环体中的下标就有可能越界;
注意点2: 因为时左闭右开区间,因此当mid被访问之后,当访问mid左边的元素时应该是[left.mid-1]
, 由于是左闭右开区间,因此当right=mid时,即[left,mid), [left.mid-1]等价于[left,mid)
[1,2,2,2,2,3,4,5] key=2
返回最左边的2,下标为1
形式1
//左闭右闭形式 public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length-1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target)//找到不立即返回 而是压缩右边界 right=mid-1; else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid-1; } // target比nums数组中的所有数字都大--->left>=nums.length //先进行left范围的判断,防止后面数组访问越界 //target不存在于数组中---->nums[left]!=target if(left>=nums.length||nums[left]!=target) return -1; return left; }
形式2
//左闭右开形式 public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length; while (left < right) {//注意点1 int mid = left + (right - left) / 2; if (nums[mid] == target) right=mid;//注意点2 else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid;//注意点3 } // target比nums数组中的所有数字都大或都小(target不存在) //先进行left范围的判断,防止后面数组访问越界 if(left>=nums.length||nums[left]!=target)//注意点4 return -1; return left; }
形式3
public int binary_search_left(int arr[],int target) { int left=0,right=arr.length-1; while(left<=right) { int mid=left+(right-left)/2; if(arr[mid]>target) right=mid-1; else if(arr[mid]<target) left=mid+1; else if(arr[mid]==target) { //当前如果arr[mid]==target再进行判断 //mid==0: 已经是最左边了 返回结果 //mid!=0 但是arr[mid-1]不等于key 说明arr[mid]是最左边的 //arr[mid-1]<arr[mid]=key.... if(mid==0||arr[mid-1]!=target) return mid; else right=mid-1; } } return -1; }
[1,2,2,2,2,3,4,5] key=2
返回最右边的2,下标为4
形式1
//左闭右闭 public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length-1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target)//找到不立即返回 压缩左边界 left=mid+1; else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid-1; } // target比nums数组中的所有数字都小/大(target不存在) //先进行right范围的判断,防止后面数组访问越界 //因为right可以取到,因此right<0时,[left,right]即为空 if(right<0||nums[right]!=target) return -1; return right;//right可以取到 返回right }
形式2
//左闭右开 public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length; while (left < right) {//注意点1 int mid = left + (right - left) / 2; if (nums[mid] == target) left=mid+1;//注意点2 else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid;//注意点3 } // target比nums数组中的所有数字都小/大(target不存在) //先进行right范围的判断,防止后面数组访问越界 //因为right取不到,因此right<=0时,[left,right)即为空 if(right<=0||nums[right-1]!=target) return -1; return right-1;//因为right取不到 所以返回right-1 }
形式3
//升序 public int binary_search_right(int arr[],int target) { int left=0,right=arr.length-1; while(left<=right) { int mid=left+(right-left)/2; if(arr[mid]<target) left=mid+1; else if(arr[mid]>target) right=mid-1; else if(arr[mid]==target) { //mid==arr.length-1: mid是最后一个位置了 直接返回 //mid不是最后一个位置 但是处于这种情况: arr[mid]=key<arr[mid+1] 因此mid是最右位置 if(mid==arr.length-1||arr[mid+1]!=target) return mid; else left=mid+1; } } return -1; }
从key开始往左寻找第一个a[i]<=key
[1,3,4,5,7,9] 4的非严格左边界是4; 6的非严格左边界是5
public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length-1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid;//如果key存在 非严格左边界就是自己 else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid-1; } //left表示小于target的元素的数量 所以最后一个小于的元素的下标就是left-1 //如果target小于数组中的所有元素 left=0 结果返回-1 表示target没有左边界 return left-1; }
从key开始往左寻找第一个a[i]<key
[1,3,4,5,7,9] 4的严格左边界是3; 6的严格左边界是5
public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length-1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target)//相等时不直接返回 而是继续往左寻找 right=mid-1; else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid-1; } //left表示小于target的元素的数量 所以最后一个小于的元素的下标就是left-1 //如果target小于数组中的所有元素 left=0 结果返回-1 表示target没有左边界 return left-1; }
从key开始往右寻找第一个a[i]>=key
[1,3,4,5,7,9] 4的非严格右边界是4; 6的非严格右边界是7
public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length-1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target)//相等时直接返回 key存在的话 右边界即自己 return mid; else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid-1; } //left表示小于target的元素的数量 所以最后一个小于的元素的下标就是left-1 //这里直接返回left 小于target的元素是[0...left-1] 则nums[left]>=target //如果left==nums.lebgth 说明targt大于数组中的所有元素 return left; }
从key开始往右寻找第一个a[i]>key
[1,3,4,5,7,9] 4的严格右边界是5; 6的严格左边界是7
public static int binary_search(int nums[], int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length-1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target)//相等时不直接返回 而是继续往左寻找 left=mid+1; else if (nums[mid] < target) left = mid + 1; else if (nums[mid] > target) right = mid-1; } //left表示小于等于target的元素的数量 所以最后一个小于等于的元素的下标就是left-1 //这里直接返回left 小于等于target的元素是[0...left-1] 则nums[left]>target //如果left==nums.lebgth 说明targt大于数组中的所有元素 return left; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。