二分查找注意事项及其变形

一、实现

public int bsearch(int[] a, int n, int value) {
  int low = 0;
  int high = n - 1;

  while (low <= high) {
    int mid = (low + high) / 2;
    if (a[mid] == value) {
      return mid;
    } else if (a[mid] < value) {
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }
  return -1;
}

二、注意事项

  •    注意循环退出条件是 low<=high,而不是 low<high。
  •    如果 low 和 high 比较大,两者之和就有可能溢出。改进方法是写成 low+((high-low)>>1)。
  •    low=mid+1,high=mid-1。注意这里的 +1 和 -1,如果直接写成 low=mid 或者 high=mid,可能会发生死循环。

 

三、变形

    变体一:查找第一个值等于给定值的元素

public int bsearch(int[] a, int n, int value) {
  int low = 0;
  int high = n - 1;
  while (low <= high) {
    int mid = low + ((high - low) >> 1);
    if (a[mid] >= value) {
      high = mid - 1;
    } else {
      low = mid + 1;
    }
  }

  if (low < n && a[low]==value) return low;
  else return -1;
}

    变体二:查找最后一个值等于给定值的元素

public int bsearch(int[] a, int n, int value) {
  int low = 0;
  int high = n - 1;
  while (low <= high) {
    int mid =  low + ((high - low) >> 1);
    if (a[mid] > value) {
      high = mid - 1;
    } else if (a[mid] < value) {
      low = mid + 1;
    } else {
      if ((mid == n - 1) || (a[mid + 1] != value)) return mid;
      else low = mid + 1;
    }
  }
  return -1;
}

    变体三:查找第一个大于等于给定值的元素

public int bsearch(int[] a, int n, int value) {
  int low = 0;
  int high = n - 1;
  while (low <= high) {
    int mid =  low + ((high - low) >> 1);
    if (a[mid] >= value) {
      if ((mid == 0) || (a[mid - 1] < value)) return mid;
      else high = mid - 1;
    } else {
      low = mid + 1;
    }
  }
  return -1;
}

    变体四:循环数组的二分查找

def cycleBsearch(lst, b):
    if len(lst) == 0:
        return -1
    low = 0
    high = len(lst) - 1
    mid = (low + high) >> 1
    while low <= high:
        if lst[mid] == b:
            return mid
        if lst[low] <= lst[mid] <= lst[high]:
            if b < lst[mid]:
                high = mid - 1
            else:
                low = mid + 1
        if lst[low] <= lst[mid] >= lst[high]:
            if lst[low] <= b < lst[mid]:
                high = mid - 1
            else:
                low = mid + 1
        if lst[low] >= lst[mid] <= lst[high]:
            if lst[mid] < b <= lst[high]:
                low = mid + 1
            else:
                high = mid - 1
        mid = (low + high) >> 1
    return -1

    变体五:查找最后一个小于等于给定值的元素

public int bsearch(int[] a, int n, int value) {
  int low = 0;
  int high = n - 1;
  while (low <= high) {
    int mid =  low + ((high - low) >> 1);
    if (a[mid] > value) {
      high = mid - 1;
    } else {
      if ((mid == n - 1) || (a[mid + 1] > value)) return mid;
      else low = mid + 1;
    }
  }
  return -1;
}
发布了94 篇原创文章 · 获赞 31 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/gaoxueyi551/article/details/103956180