[关闭]
@MrXiao 2018-03-08T16:39:40.000000Z 字数 2639 阅读 800

二分查找

算法


二分查找法是对一组有序的数字中进行查找,传递相应的数据,进行比较查找到与原数据相同的数据,查找到了返回对应的数组下标,没有找到返回-1;

1、基本二分查找实现

  1. while循环

    1. /**
    2. * 循环实现
    3. * @param array 已排序数组
    4. * @param target 目标
    5. * @return 找不到返回-1,找到返回下标
    6. */
    7. private static int binarySearch(int[] array, int target) {
    8. int low = 0;
    9. int high = array.length - 1;
    10. while (low <= high) {
    11. int mid = low + (high - low) / 2; //注意此处写法,避免越界
    12. if (array[mid] > target) {
    13. high = mid - 1;
    14. } else if (array[mid] < target) {
    15. low = mid + 1;
    16. } else {
    17. return mid;
    18. }
    19. }
    20. return -1;
    21. }
  2. 递归实现

    1. private static int binarySearch(int[] array, int target, int low, int high) {
    2. int mid = low + (high - low) / 2;
    3. if (array[mid] == target) {
    4. return mid;
    5. }
    6. if (low >= high) {
    7. return -1;
    8. } else if (target > array[mid]) {
    9. return binarySearch(array, target, mid + 1, high);
    10. } else if (target < array[mid]) {
    11. return binarySearch(array, target, low, mid - 1);
    12. }
    13. return -1;
    14. }

2、变形

随着二分查找的进行,如果找到key并不结束循环的话,最终的结束状态会是right < left,并且right + 1 = left。

此处输入图片的描述

那么,可以找到:

  1. 最后一个小于key的元素 1 左right
  2. 第一个大于等于key的元素 2 左left
  3. 最后一个小于等于key的元素 2 右right
  4. 第一个大于key的元素 5 右left

另外,如果存在多个key时,稍加判断,就可以找到

  1. 第一个与key相等的元素
  2. 最后一个与key相等的元素
  1. while (left <= right) {
  2. mid = (left + right) / 2;
  3. if (key ? arr[mid]) {
  4. right = mid - 1;
  5. } else {
  6. left = mid + 1;
  7. }
  8. }
  9. return ?;

根据要求的值的位置,先确定比较符号,再确定返回值,
比较符号:左<=,右<
返回值:左right,右left

2.1 查找最后一个小于key的元素

  1. //1 查找最后一个小于key的元素
  2. int findLastLess(int arr[], int len, int key) {
  3. int left = 0;
  4. int right = len - 1;
  5. int mid;
  6. while (left <= right) {
  7. mid = left + (right - left) / 2;
  8. if (key <= arr[mid]) { // <= 意为左
  9. right = mid - 1;
  10. } else {
  11. left = mid + 1;
  12. }
  13. }
  14. return right; //返回左边值right
  15. }

2.2 查找第一个大于等于key的元素

  1. //2 查找第一个大于等于key的元素
  2. int findLastLess(int arr[], int len, int key) {
  3. int left = 0;
  4. int right = len - 1;
  5. int mid;
  6. while (left <= right) {
  7. mid = left + (right - left) / 2;
  8. if (key <= arr[mid]) { // <= 意为左
  9. right = mid - 1;
  10. } else {
  11. left = mid + 1;
  12. }
  13. }
  14. return left; //返回右边值left
  15. }

2.3 查找最后一个小于等于key的元素

  1. //3 查找第一个大于等于key的元素
  2. int findLastLess(int arr[], int len, int key) {
  3. int left = 0;
  4. int right = len - 1;
  5. int mid;
  6. while (left <= right) {
  7. mid = left + (right - left) / 2;
  8. if (key < arr[mid]) { // <= 意为右
  9. right = mid - 1;
  10. } else {
  11. left = mid + 1;
  12. }
  13. }
  14. return right; //返回左边值right
  15. }

2.4 查找第一个大于key的元素

  1. //4 查找第一个大于key的元素
  2. int findLastLess(int arr[], int len, int key) {
  3. int left = 0;
  4. int right = len - 1;
  5. int mid;
  6. while (left <= right) {
  7. mid = left + (right - left) / 2;
  8. if (key < arr[mid]) { // <= 意为右
  9. right = mid - 1;
  10. } else {
  11. left = mid + 1;
  12. }
  13. }
  14. return left; //返回右边值left
  15. }

2.5 查找第一个与key相等的元素

  1. //5 查找第一个与key相等的元素
  2. int findFirstEqual(int arr[], int len, int key) {
  3. int left = 0;
  4. int right = len - 1;
  5. int mid;
  6. while (left <= right) {
  7. mid = left + (right - left) / 2;
  8. if (key <= arr[mid]) { // <= 意为左
  9. right = mid - 1;
  10. } else {
  11. left = mid + 1;
  12. }
  13. }
  14. //right是最后一个小于key的
  15. //left是第一个大于等于key的
  16. if (left < len && arr[left] == key) {
  17. return left;
  18. }
  19. return -1;
  20. }

2.6 查找最后一个与key相等的元素

  1. //6 查找最后一个与key相等的元素
  2. int findLastEqual(int arr[], int len, int key) {
  3. int left = 0;
  4. int right = len - 1;
  5. int mid;
  6. while (left <= right) {
  7. mid = left + (right - left) / 2;
  8. if (key < arr[mid]) { // < 意为右
  9. right = mid - 1;
  10. } else {
  11. left = mid + 1;
  12. }
  13. }
  14. //right是最后一个小于key的
  15. //left是第一个大于等于key的
  16. if (right >= 0 && arr[right] == key) {
  17. return right;
  18. }
  19. return -1;
  20. }

参考资料

你真的会写二分查找吗?-搏风雨

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注