文章目录

  • 你不知道的事
  • 骚算法
  • 测试
  • 测试结果

你不知道的事

你肯定听说过在有序数组中,通过二分算法查找等于指定的值?但是…

你是否听说过在有序数组中,通过二分算法查找大于等于指定的值的最左下标?

你是否听说过在有序数组中,通过二分算法查找小于等于指定的值的最右下标?

你是否听说过在无序数组中,也可以用二分算法?知道如何用二分算法解决局部最小值问题吗?

骚算法

package com.nobody.search;/*** @author Mr.nobody* @Description 二分查找* @date 2020/9/5*/
public class Code01_BinarySearch {// 二分查找,在有序数组中查找指定值,找到返回下标,否则返回-1public static int binarySearch(int[] sortedArr, int num) {if (null == sortedArr || sortedArr.length == 0) {return -1;}int left = 0;int right = sortedArr.length - 1;int mid = 0;while (left <= right) {// 等同于mid = (left + right) / 2;// 但是下面的表达式既速度快,还能避免left+right溢出mid = left + ((right - left) >> 1);if (sortedArr[mid] == num) {return mid;} else if (sortedArr[mid] > num) {right = mid - 1;} else {left = mid + 1;}}return -1;}// 二分查找,在有序数组中查找大于等于指定值的最左的数,找到返回下标,否则返回-1// 例如数组[1, 2, 2, 5, 8, 10, 11, 11, 11, 20],指定值为2,则返回下标1// 指定值为7,则返回下标为4;指定值为0,返回下标0;指定值为25,则返回下标-1public static int greaterEqualBinarySearch(int[] sortedArr, int num) {if (null == sortedArr || sortedArr.length == 0) {return -1;}int left = 0;int right = sortedArr.length - 1;int mid = 0;// 记录满足的最左下标int mostLeftIndex = -1;while (left <= right) {// 等同于mid = (left + right) / 2;// 但是下面的表达式既速度快,还能避免left+right溢出mid = left + ((right - left) >> 1);if (sortedArr[mid] >= num) {mostLeftIndex = mid;right = mid - 1;} else {left = mid + 1;}}return mostLeftIndex;}// 二分查找,在有序数组中查找小于等于指定值的最右的数,找到返回下标,否则返回-1// 例如数组[1, 2, 2, 5, 8, 10, 11, 11, 11, 20],指定值为2,则返回下标2// 指定值为7,则返回下标为3;指定值为0,返回下标-1;指定值为25,则返回下标9public static int lessEqualBinarySearch(int[] sortedArr, int num) {if (null == sortedArr || sortedArr.length == 0) {return -1;}int left = 0;int right = sortedArr.length - 1;int mid = 0;// 记录满足的最右下标int mostRightIndex = -1;while (left <= right) {// 等同于mid = (left + right) / 2;// 但是下面的表达式既速度快,还能避免left+right溢出mid = left + ((right - left) >> 1);if (sortedArr[mid] <= num) {mostRightIndex = mid;left = mid + 1;} else {right = mid - 1;}}return mostRightIndex;}// 二分查找,在数组中(不一定要有序)查找局部最小数(随便一个就可以),找到返回下标,否则返回-1// 何为局部最小值,当某一个位置i的数,只要小于等于i-1和i+1位置的数时,即i位置的数就是局部最小值// 如果不存在i-1或i+1位置,就不需要比较,例如0位置的数只需要小于等于1位置的数即可;// n-1位置的数只需要小于等于n-2位置的数即可;public static int localMinBinarySearch(int[] arr) {if (null == arr || arr.length == 0) {return -1;}if (arr.length == 1 || arr[0] <= arr[1]) {return 0;}if (arr[arr.length - 1] <= arr[arr.length - 2]) {return arr.length - 1;}// 既然数组头部和尾部都不满足局部最小值,那肯定整个数据区间是↘...↗走势// 则可以从中间切入,局部最小肯定在中间,左区间或者右区间存在,// 按此逻辑进行二分查找下去即可int left = 0;int right = arr.length - 1;int mid = 0;while (left <= right) {// 等同于mid = (left + right) / 2;// 但是下面的表达式既速度快,还能避免left+right溢出mid = left + ((right - left) >> 1);if (arr[mid - 1] >= arr[mid] && arr[mid] <= arr[mid + 1]) {// 既小于等于左边,又小于等于右边,满足局部最小值return mid;} else if (arr[mid - 1] < arr[mid]) {// 大于左边,则左边是↘...↗走势,那肯定在左边区间一定存在局部最小值right = mid - 1;} else if (arr[mid] > arr[mid + 1]) {// 大于右边,则右边是是↘...↗走势,那肯定在右边区间一定存在局部最小值left = mid + 1;}}return -1;}
}

测试

package com.nobody.search;import com.nobody.sort.Code01_InsertionSort;import java.util.Arrays;/*** @author Mr.nobody* @Description* @date 2020/9/6*/
public class Main {public static void main(String[] args) {int[] arr = {1, 2, 2, 5, 8, 10, 11, 11, 11, 20};int num = 2;System.out.print("有序数组:");Arrays.stream(arr).forEach(e -> System.out.print(e + " "));System.out.println();System.out.println("待查找数:" + num);System.out.println("查找的下标:" + Code01_BinarySearch.binarySearch(arr, num));System.out.println("----------------------------------------");System.out.println("大于等于的数:" + 2 + ",最左下标为:"+ Code01_BinarySearch.greaterEqualBinarySearch(arr, 2));System.out.println("大于等于的数:" + 7 + ",最左下标为:"+ Code01_BinarySearch.greaterEqualBinarySearch(arr, 7));System.out.println("大于等于的数:" + 0 + ",最左下标为:"+ Code01_BinarySearch.greaterEqualBinarySearch(arr, 0));System.out.println("大于等于的数:" + 25 + ",最左下标为:"+ Code01_BinarySearch.greaterEqualBinarySearch(arr, 25));System.out.println("----------------------------------------");System.out.println("小于等于的数:" + 2 + ",最右下标为:"+ Code01_BinarySearch.lessEqualBinarySearch(arr, 2));System.out.println("小于等于的数:" + 7 + ",最右下标为:"+ Code01_BinarySearch.lessEqualBinarySearch(arr, 7));System.out.println("小于等于的数:" + 0 + ",最右下标为:"+ Code01_BinarySearch.lessEqualBinarySearch(arr, 0));System.out.println("小于等于的数:" + 25 + ",最右下标为:"+ Code01_BinarySearch.lessEqualBinarySearch(arr, 25));System.out.println("----------------------------------------");int[] arr1 = {1, 2, 2, 10, 8, 4, 2, 11, 7, 20};System.out.print("数组:");Arrays.stream(arr1).forEach(e -> System.out.print(e + " "));System.out.println(",局部最小值下标:" + Code01_BinarySearch.localMinBinarySearch(arr1));int[] arr2 = {4, 2, 2, 10, 8, 4, 2, 11, 7, 5};System.out.print("数组:");Arrays.stream(arr2).forEach(e -> System.out.print(e + " "));System.out.println(",局部最小值下标:" + Code01_BinarySearch.localMinBinarySearch(arr2));int[] arr3 = {7, 2, 2, 10, 8, 4, 2, 11, 7, 20};System.out.print("数组:");Arrays.stream(arr3).forEach(e -> System.out.print(e + " "));System.out.println(",局部最小值下标:" + Code01_BinarySearch.localMinBinarySearch(arr3));int[] arr4 = {3, 2, 4, 10, 8, 6, 7, 11, 7, 10};System.out.print("数组:");Arrays.stream(arr4).forEach(e -> System.out.print(e + " "));System.out.println(",局部最小值下标:" + Code01_BinarySearch.localMinBinarySearch(arr4));}
}

测试结果

有序数组:1 2 2 5 8 10 11 11 11 20
待查找数:2
查找的下标:1
----------------------------------------
大于等于的数:2,最左下标为:1
大于等于的数:7,最左下标为:4
大于等于的数:0,最左下标为:0
大于等于的数:25,最左下标为:-1
----------------------------------------
小于等于的数:2,最右下标为:2
小于等于的数:7,最右下标为:3
小于等于的数:0,最右下标为:-1
小于等于的数:25,最右下标为:9
----------------------------------------
数组:1 2 2 10 8 4 2 11 7 20 ,局部最小值下标:0
数组:4 2 2 10 8 4 2 11 7 5 ,局部最小值下标:9
数组:7 2 2 10 8 4 2 11 7 20 ,局部最小值下标:6
数组:3 2 4 10 8 6 7 11 7 10 ,局部最小值下标:5

最骚操作的二分查找,秀儿?相关推荐

  1. 单链表的操作_二分查找

    void BinSearch(SqList* sql, EleType x) //二分查找应用于已经排序好的数据 { assert(sql); if(sql->size > 0) { in ...

  2. LeetCode4_编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ““。(解决方案:横向扫描、 纵向扫描 、分治 二分查找 、秀儿操作之排序比较头尾)

    题目 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow&q ...

  3. 【数据结构与算法】二分查找

    一.什么是二分查找? 二分查找针对的是一个有序的数据集合,每次通过跟区间中间的元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间缩小为0. 二.时间复杂度分析? 1.时间复杂度 ...

  4. 第十九章:二分查找和二分答案

    二分查找 二分的思想在程序设计中有着广泛的应用,例如,排序算法中的快速排序.归并排序,数据结构中的二叉树.堆.线段树等.二分是一种常用且高效的算法,它的基本用途是在单调序列中进行查找和判定操作. 二分 ...

  5. mysql 查找相似数据_数据库存储引擎大揭秘,不看不知道这里面的骚操作可真多!...

    吊打各种树这篇文章 带大家学习一遍数据结构中的各种树,对数据结构还不够熟悉的同学,那篇文章可以作为基础入门,我画了很多图理解起来不困难,建议回头先学习下那篇文章,更容易理解本文要讲的内容. 文章里有提 ...

  6. 2022-04-07 西安 javaSE(04) 方法可变参数、重载、递归,数组、冒泡排序、二分查找、动态操作,二维数组、jvm内存区域划分

    方法 1.方法传递参数 形参是基本类型: 1.参数传递的内容是该基本类型的数据值.   2.对形式参数的改变不会影响实际参数的数据值 形参是引用类型:     1.参数传递的是地址值     2.对形 ...

  7. 数据分析学习 excel的骚操作合集(则秀excel课程笔记)

    文章目录 前言 一.自动填充 二.选取区域 三.复制与粘贴 四.公式与函数 五.输入公式 六.快速求和 七.绝对引用 八.if函数 九.sumif,averageif函数 十.定义名称 十一.数字与数 ...

  8. 计算机课gif,GIF动图:一同学发来开学第一天计算机课就大秀骚操作,全班同学都五体涂地...

    原标题:GIF动图:一同学发来开学第一天计算机课就大秀骚操作,全班同学都五体涂地 一同学发来开学第一天计算机课就大秀骚操作,全班同学都懵逼五体涂地了 主人偷偷出门被大鹅看见,直勾勾的跑出来 这谁的责任 ...

  9. 学生成绩管理系统利用数据结构顺序表来进行二分查找,直接插入,快速排序操作

    一.实验目的 1.掌握查找的不同方法,并能用高级语言实现查找算法. 2.熟练掌握顺序表和有序表的顺序查找和二分查找方法. 3.掌握排序的不同方法,并能用高级语言实现排序算法. 4.熟练掌握顺序表的选择 ...

最新文章

  1. letswave7中文教程1:软件安装与脑电数据导入
  2. Linux学习记录-11
  3. Android ListView不响应OnItemClickListener解决办法
  4. 对象key值为数字时的处理
  5. stage3d 骨骼优化
  6. mblog Mtons博客系统
  7. java8 Optional源码
  8. servlet-cookie实现向客户端写cookie信息
  9. 简单的Postman,硬是玩出花!我能咋办
  10. 《战争论》第四篇《战斗》的主要内容
  11. Windows | 常用软件
  12. 设计模式笔记2-简单工厂模式(带有自制UML类图)
  13. java excel 冻结_Java 冻结、解除冻结 Excel 的行和列
  14. pwn|软件安全相关问题学习笔记
  15. 构建自己的人脉网络——高科技人才在跨国大公司的生存之道(四)
  16. czl蒻蒟的OI之路8
  17. 苏嵌//张朋//2018.07.16
  18. Linux下GPT分区,gdisk修复损坏的分区表
  19. eclipse取消默认工作空间的两种方法
  20. vue-barcode生成条形码

热门文章

  1. 两个Linux下的免费视频编辑软件
  2. Android 实现类似九宫格的程序锁
  3. Android快应用开发(一)
  4. 面向制药行业MES的研究
  5. 高并发下如何生成随机数
  6. alloc 原理的学习
  7. MacOS 重置网络配置
  8. metamask方法使用获取账户信息
  9. Qt实战小工具 -- 简易Gif制作工具
  10. 白色运动鞋保养完全攻略