二分查找注意事項及其變形

一、實現

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;
}

 

發佈了92 篇原創文章 · 獲贊 31 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章