千锋教育-做有情怀、有良心、有品质的职业教育机构

当前位置:首页  >  关于学院  >  技术干货  >  Java技术干货  >  正文

什么是二分查找法?

来源:千锋教育
作者:qyf
关键词: 查找 int
2023-03-23
分享

  简介

  我们对数组除了可以进行排序之外,还能对数组中的元素进行查找,其中一个比较经典的方案是利用二分查找法,也叫做折半查找法进行实现,可以缩小查找范围,提高查找效率。

  二分查找是一种效率较高的查找方法,要求数据表须采用顺序存储结构,且数组是有序(升序或者降序)的。核心思路就是将待查找的元素与中间下标对应的元素进行比较,如果大于中间下标对应的元素,则去右半部分查找,否则就去左半部分进行查找。基本实现流程如下:

  ●首先,我们假设数组中的元素是按升序排列的;

  ●然后将数组中间位置记录的关键字与查找关键字进行比较,如果两者相等,则查找成功;

  ●否则就利用中间的位置记录,将数组分成前、后两个子部分。如果中间位置记录的关键字大于查找关键字,则进一步查找前一子部分,否则进一步查找后一子部分;

  ●重复以上过程,直到找到满足条件的记录为止。或直到子部分不存在为止,此时查找不成功。

  实现案例

  然后就按照上述思路,给大家设计了如下案例,大家可以对照练习,好好琢磨该案例。

  public class Demo14 {

  public static void main(String[] args) {

  // 二分查找法--折半查找法

  // 遍历排序后的数组

  int[] arr = { 1, 3, 46, 22, 11 };

  int index = search(arr,46);

  System.out.println("46所在的索引位置="+index);

  }

  //定义一个方法,实现二分查找

  public static int search(int[] arr,int num) {

  //1. 获取最小、大值的下标

  int min = 0;

  int max = arr.length -1;

  while(min <= max) {

  //2. 获取中间值的下标

  int middle = (min + max) / 2;

  //3. 将要查找的数字与中间值做比较

  if(num > arr[middle]) {

  min = middle +1;

  }else if(num < arr[middle]) {

  max = middle -1;

  }else {

  return middle;

  }

  }

  return -1;

  }

  }

  3.二分查找法的常见写法

  1.非递归写法

  int binarySearch(int[] nums, int target) {

  int left = 0, right = nums.length - 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;

  }

  2.递归写法

  int binarySearch(int[] nums, int target, int left, int right) {

  if (left > right) {

  return -1;

  }

  int mid = left + (right - left) / 2;

  if (nums[mid] == target) {

  return mid;

  } else if (nums[mid] < target) {

  return binarySearch(nums, target, mid + 1, right);

  } else {

  return binarySearch(nums, target, left, mid - 1);

  }

  }

  3.查找第一个等于目标值的元素

  int binarySearch(int[] nums, int target) {

  int left = 0, right = nums.length - 1;

  while (left <= right) {

  int mid = left + (right - left) / 2;

  if (nums[mid] < target) {

  left = mid + 1;

  } else if (nums[mid] > target) {

  right = mid - 1;

  } else {

  if (mid == 0 || nums[mid - 1] != target) {

  return mid;

  } else {

  right = mid - 1;

  }

  }

  }

  return -1;

  }

  4.查找最后一个等于目标值的元素

  int binarySearch(int[] nums, int target) {

  int left = 0, right = nums.length - 1;

  while (left <= right) {

  int mid = left + (right - left) / 2;

  if (nums[mid] < target) {

  left = mid + 1;

  } else if (nums[mid] > target) {

  right = mid - 1;

  } else {

  if (mid == nums.length - 1 || nums[mid + 1] != target) {

  return mid;

  } else {

  left = mid + 1;

  }

  }

  }

  return -1;

  }

  5.查找第一个大于等于目标值的元素

  int binarySearch(int[] nums, int target) {

  int left = 0, right = nums.length - 1;

  while (left <= right) {

  int mid = left + (right - left) / 2;

  if (nums[mid] < target) {

  left = mid + 1;

  } else {

  if (mid == 0 || nums[mid - 1] < target) {

  return mid;

  } else {

  right = mid - 1;

  }

  }

  }

  return -1;

  }

  6.查找最后一个小于等于目标值的元素

  int binarySearch(int[] nums, int target) {

  int left = 0, right = nums.length - 1;

  while (left <= right) {

  int mid = left + (right - left) / 2;

  if (nums[mid] > target) {

  right = mid - 1;

  } else {

  if (mid == nums.length - 1 || nums[mid + 1] > target) {

  return mid;

  } else {

  left = mid + 1;

  }

  }

  }

  return -1;

  }

  常见的二分查找法写法的区别

  1.二分查找有多种写法,主要区别在于查找的目标不同,以及实现方式的不同。非递归写法和递归写法的区别在于实现方式不同,递归写法的代码更加简洁,但是会消耗额外的栈空间。

  2.查找第一个等于目标值的元素、查找最后一个等于目标值的元素、查找第一个大于等于目标值的元素、查找最后一个小于等于目标值的元素等,主要区别在于对于目标值相等的元素的处理方式不同,需要特别判断。

  3.另外,二分查找还有一种写法是针对旋转排序数组的,即先找到旋转点,再根据目标值所在的区间进行查找。这种写法和普通的二分查找的区别在于需要先找到旋转点。

  总的来说,不同的二分查找写法主要针对不同的问题进行了优化,选择哪种写法取决于具体的问题情况。

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

相关推荐

  • springcloud和dubbo的区别是什么? SpringCloud和Dubbo是两个在分布式系统开发中常用的框架,它们有以下几个主要区别:1.生态系统和发展历程:-Dubbo是由阿里巴巴集团开发并开源的,主要在中国的互联网企业中广泛使用,并且有
  • dubbo是什么?有哪些特性?-小王 Dubbo是一个开源的高性能RPC(远程过程调用)框架,由阿里巴巴集团开发并开源。它提供了分布式服务治理的解决方案,旨在简化大规模分布式系统中服务之间的通信和调用。Dubbo的设计目标是提供高性能、透
  • java面试之消息队列mq的实现原理 消息队列(MessageQueue)是一种在应用程序之间传递消息的通信模式。它提供了一种异步的、解耦的方式来实现不同系统、模块或组件之间的通信。消息队列的实现原理可以简要概括如下:1.**消息发布(P
  • java hash 加密字符串,使用 MessageDigest 类 在Java中,可以使用MessageDigest类来进行哈希加密(散列算法)。下面是使用MessageDigest类进行字符串哈希加密的示例:importjava.security.MessageDi
  • java object添加属性怎么实现? 在Java中,一个对象的属性通常是在类的定义中声明的,并通过类的构造函数或方法来进行初始化和设置。但是,如果你想为一个已有的对象动态添加属性,Java并没有直接支持这种操作。然而,你可以使用其他方式来
  • stringbuilder字符串 StringBuilder是一个用于构建和操作字符串的类,通常用于需要频繁拼接和修改字符串的场景,特别是在循环中。在许多编程语言中都有类似于StringBuilder的概念,下面是一个Java语言中使