[LeetCode&Algorithms]34.Find First and Last Position of Element/二分查找/第一个key/最后一个key/中间值mid的取值趋向

什么是二分

数组必须有序。使用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)));
 }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值