二分查找的三种模板(C++,Java,Python)

简介

二分查找是一种在每次比较之后将查找空间一分为二的算法。二分查找的最大特点是:思路简单,实现很难。其原因是二分查找需要考虑循环的终止条件、mid的选取等细节,如果这些细节处理不当,稍有不慎就会出现问题。所以实际上二分查找仍是一个比较难的问题。

模板

模板1

基础模板。
C++

int binarySearch(vector& nums, int target){
  if(nums.size() == 0)
    return -1;

  int left = 0, right = nums.size() - 1;
  while(left <= right){
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid - 1; }
  }

  return -1;
}

Java

int binarySearch(int[] nums, int target){
  if(nums == null || nums.length == 0)
    return -1;

  int left = 0, right = nums.length - 1;
  while(left <= right){
    // Prevent (left + right) overflow
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid - 1; }
  }
  return -1;
}

Python

def binarySearch(nums,target):
    """
    :type nums: List[int]
    :type target: int
    :rtype: int
    """
    if len(nums) == 0:
        return -1
    left,right = 0,len(nums) - 1
    while left <= right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
return -1
模板2

高级模板。用于查找需要访问数组中当前索引及其直接右邻居索引的元素或条件。
C++

int binarySearch(vector& nums, int target){
  if(nums.size() == 0)
    return -1;

  int left = 0, right = nums.size();
  while(left < right){
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid; }
  }

  if(left != nums.size() && nums[left] == target) return left;
  return -1;
}

Java

int binarySearch(int[] nums, int target){
  if(nums == null || nums.length == 0)
    return -1;

  int left = 0, right = nums.length;
  while(left < right){
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid; }
  }

  if(left != nums.length && nums[left] == target) return left;
  return -1;
}

Python

def binarySearch(nums,target):
    """
    :type nums: List[int]
    :type target: int
    :rtype: int
    """
    if len(nums) == 0:
        return -1
    left,right = 0,len(nums)
    while left < right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid
            
    if left != len(nums) and nums[left] == target:
        return left
    return -1
模板3

另一种独特形式。用于搜索需要访问当前索引及其在数组中的直接左右邻居索引的元素或条件。
C++

int binarySearch(vector& nums, int target){
    if (nums.size() == 0)
        return -1;

    int left = 0, right = nums.size() - 1;
    while (left + 1 < right){
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid;
        } else {
            right = mid;
        }
    }

    if(nums[left] == target) return left;
    if(nums[right] == target) return right;
    return -1;
}

Java

int binarySearch(int[] nums, int target) {
    if (nums == null || nums.length == 0)
        return -1;

    int left = 0, right = nums.length - 1;
    while (left + 1 < right){
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid;
        } else {
            right = mid;
        }
    }

    if(nums[left] == target) return left;
    if(nums[right] == target) return right;
    return -1;
}

Python

def binarySearch(nums,target):
    """
    :type nums: List[int]
    :type target: int
    :rtype: int
    """
    if len(nums) == 0:
        return -1
    left,right = 0,len(nums) - 1
    while left + 1 < right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid
        else:
            right = mid
            
    # Post-processing:
    # End Condition: left + 1 == right
    if nums[left] == target:return left
    if nums[right] == target:return right
    return -1

这 3 个模板的不同之处在于:

  • 左、中、右索引的分配。
  • 循环或递归终止条件。
  • 后处理的必要性。

你可能感兴趣的:(二分查找的三种模板(C++,Java,Python))