常见的查找算法

前提:除了线性查找外,下面的其他查找算法适用于有序数组(以从小到大为例)

一、线性查找

/*** 这里若要查找重复出现的数,可以把索引放入到一个集合中* @param arr* @param value* @return 如果没有找到,则返回 -1*/public static int seqSearch(int[] arr, int value) {for (int i = 0; i < arr.length; i++) {if (arr[i] == value) {return i;}}return -1;}

二、二分查找

public static int binarySearch(int[] arr, int left, int right, int value) {// 数组中不含有指定的数if (left > right) {return -1;}int midIndex = (left + right) / 2;// 中间索引int midValue = arr[midIndex];if (value > midValue) {// 向右递归return binarySearch(arr, midIndex + 1, right, value);} else if (value < midValue) {// 向左递归return binarySearch(arr, left, midIndex - 1, value);} else {return midIndex;}}

 上面的代码,对于重复出现的元素没有处理,下面的代码将作出处理

// 完成一个课后思考题// int[] arr = { 1, 8, 10, 89, 1000, 1000, 1234 };// 解决重复元素全部输出的问题,比如1000// 思路:// 在找到对应的值后先不要返回,分别向右和左进行查找,看看有没有和他相等的值,有的话就放到一个集合中public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int value) {System.out.println("查找的次数");// 数组中不含有指定的数if (left > right) {return new ArrayList<Integer>();}int midIndex = (left + right) / 2;// 中间索引int midValue = arr[midIndex];if (value > midValue) {// 向右递归return binarySearch2(arr, midIndex + 1, right, value);} else if (value < midValue) {// 向左递归return binarySearch2(arr, left, midIndex - 1, value);} else {// 向左查找ArrayList<Integer> resIndexList = new ArrayList<Integer>();int leftIndex = midIndex - 1;while (true) {if (leftIndex < 0 || arr[leftIndex] != value) {// 因为数组是有序数组,所以若向左没有发现,那么退出循环break;}// 否则,就将对应的索引加入到集合中resIndexList.add(leftIndex);leftIndex--;}resIndexList.add(midIndex);// 将第一次找到的索引加入到集合中// 向右查找int rightIndex = midIndex + 1;while (true) {if (leftIndex > arr.length - 1 || arr[rightIndex] != value) {// 若向右没有发现,那么退出循环break;}// 否则,就将对应的索引加入到集合中resIndexList.add(rightIndex);rightIndex++;}return resIndexList;}}

尝试用二分法做,提高性能 

LeetCode高频题69. x 的平方根,二分法搞定,非常简单_分治法求解计算并返回x的平方根。-CSDN博客

力扣287题(用二分法做,提高性能)

三、插值查找

本质:将二分查找的midIndex(中间索引)改成:

int midIndex = left + (right - left) * (value - arr[left]) / (arr[right] - arr[left]);

public static int binarySearch1(int[] arr, int left, int right, int value) {// 数组中不含有指定的数// arr[left] > value || arr[right] < value不能少,否则midIndex过大,可能会越界System.out.println("查找的次数");if (left > right || arr[left] > value || arr[right] < value) {return -1;}int midIndex = left + (right - left) * (value - arr[left]) / (arr[right] - arr[left]);// 中间索引int midValue = arr[midIndex];if (value > midValue) {// 向右递归return binarySearch1(arr, midIndex + 1, right, value);} else if (value < midValue) {// 向左递归return binarySearch1(arr, left, midIndex - 1, value);} else {return midIndex;}}

上面的代码,对于重复出现的元素没有处理,下面的代码将作出处理

// 解决重复元素全部输出的问题public static ArrayList<Integer> binarySearch2(int[] arr, int left, int right, int value) {// 数组中不含有指定的数// arr[left] > value || arr[right] < value不能少,否则midIndex过大,可能会越界System.out.println("查找的次数");if (left > right || arr[left] > value || arr[right] < value) {return new ArrayList<Integer>();}int midIndex = left + (right - left) * (value - arr[left]) / (arr[right] - arr[left]);// 中间索引int midValue = arr[midIndex];if (value > midValue) {// 向右递归return binarySearch2(arr, midIndex + 1, right, value);} else if (value < midValue) {// 向左递归return binarySearch2(arr, left, midIndex - 1, value);} else {// 向左查找ArrayList<Integer> resIndexList = new ArrayList<Integer>();int leftIndex = midIndex - 1;while (true) {if (leftIndex < 0 || arr[leftIndex] != value) {// 因为数组是有序数组,所以若向左没有发现,那么退出循环break;}// 否则,就将对应的索引加入到集合中resIndexList.add(leftIndex);leftIndex--;}resIndexList.add(midIndex);// 将第一次找到的索引加入到集合中// 向右查找int rightIndex = midIndex + 1;while (true) {if (leftIndex > arr.length - 1 || arr[rightIndex] != value) {// 若向右没有发现,那么退出循环break;}// 否则,就将对应的索引加入到集合中resIndexList.add(rightIndex);rightIndex++;}return resIndexList;}}

 注意:插值查找算法适用于数据分布均匀,数组中数量较多的数组,对于数据分布不均匀的数组,此方法未必有二分查找算法好;

四、斐波那契查找算法(黄金分割搜索算法)

// 先得到斐波那契数列// 因为后面要用到mid = low + F(k-1)-1public static int[] fib() {int[] f = new int[20];f[0] = 1;f[1] = 1;for (int i = 2; i < maxSize; i++) {f[i] = f[i - 1] + f[i - 2];}return f;}/*** * @param a   要查找的数组* @param key 要找的值* @return 如果找到,则返回下标,否则返回-1*/// 开始编写斐波那契查找算法public static int fibSearch(int[] a, int key) {int low = 0;int high = a.length - 1;// high是最大的索引int k = 0;// 表示斐波那契的数列的下标int mid = 0;// 存放mid的值int[] f = fib();// 获取当前的斐波那契数列// 获取到当前斐波那契的下标,即当斐波那契数列中的 一个数 大于或等于 数组的长度时才停止while (f[k] <= high + 1) {// high + 1为整个数组的长度k++;}// 找到k的值// 因为f[k]的值可能会大于数组a的长度,所以要将数组a给补全,// 即让数组a的长度和f[k]的值一样(用Arrays提供的一个方法)int[] temp = Arrays.copyOf(a, f[k]);// 长度不够,用零来凑// 将数组后面几位0赋值成 数组对应的最后一位的值for (int i = high + 1; i < temp.length; i++) {temp[i] = a[high];}// 使用while循环来找到我们的keywhile (low <= high) {mid = low + f[k - 1] - 1;// 公式if (key < temp[mid]) {// 向数组的左边找high = mid - 1;k--;// 为什么是k--// 1.全部元素 = 前面的元素 + 后面的元素// 即 f[k] = f[k-1] + f[k-2]// 2.因为前面有f[k-1]个元素,所以可以继续拆分f[k-1] = f[k-2] + f[k-3]// 即在f[k-1]的前面继续查找// 即下次循环 mid = f[k-1-1]-1} else if (key > temp[mid]) {low = mid + 1;k -= 2;// 为什么是 k-= 2// 1.全部元素 = 前面的元素 + 后面的元素// 即 f[k] = f[k-1] + f[k-2]// 2.因为后面有f[k-2]个元素,所以可以继续拆分f[k-2] = f[k-3] + f[k-4]// 即在f[k-5]的前面继续查找// 即下次循环mid = f[k-1-2]-1} else {// 此时key = temp[mid] 找到// 需要确定,返回的是哪一个下标// 要返回较小的值,因为temp数组是我们自己补全的 mid可能会大于highif (mid <= high) {return mid;} else {return high;}}}return -1;// 上面的全部执行完后,如果还没有找到,那么就返回-1}

 上面的代码只实现了对一个元素的输出

思考:用斐波那契查找算法实现输出  全部重复元素  的索引。

比如:int[] arr = { 1, 8, 10, 89, 1000, 1000, 1234 };

查找 1000,返回索引

输出:[4  5]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/632020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

联合体中嵌套结构体,结构体未命名时,结构体成员变量的引用

参考文章&#xff1a;C语言 结构体 联合体 | 嵌套使用_联合体里面嵌套结构体-CSDN博客 如题&#xff0c;其实直接用 联合体名.结构体成员变量名 即可。 程序&#xff1a; #include <stdio.h>typedef unsigned int uint32_t; typedef unsigned char uint8_t;union b…

GNSS数据下载软件 -- 武汉大学 Fast软件(体验感极佳~)

目录 一、简介与下载地址 1.介绍 2.软件特点 3.下载地址 4.以github下载链接为例 二、下载方法(三种方法&#xff0c;以windows系统为例) 1.双击"Fast.exe"根据提示引导下载 2.手动输入"cmd"进入命令行界面&#xff0c;通过输入相关命令进行下载 …

el-date-picker如果超过限制跨度则提示

需求&#xff1a;实现日期时间选择组件跨度如果超过限制天数&#xff0c;点击查询则提示超过限制时间 封装一个方法&#xff0c;传入开始和结束时间以及限制天数&#xff0c;如果超过则返回false //计算时间跨度是否超过限制天数isTimeSpanWithinLimit(startTime, endTime, li…

Python编程之旅7:函数

欢迎来到第七篇《Python编程之旅》的博客&#xff01;在前面的几篇博客中&#xff0c;我们已经学习了Python的基本语法、数据类型、流程控制语句以及列表、元组和字典等内容。今天&#xff0c;我们将进一步探索Python编程的世界&#xff0c;重点关注函数。 函数 函数是一种可…

AIOps探索 | 应急处置中排障的降本增效方法探索

原作者&#xff1a;擎创科技 资深产品专家 布博士 前言 在事件管理及应急场景的场景下&#xff0c;一般会造成业务服务和技术服务故障&#xff08;如应用系统、微服务架构等不同的技术组件&#xff09;。为了实现对业务的影响分析、查看技术组件的相互依赖关系以及进行根因排…

WSL中Ubuntu出现过的问题!!!

1. 问题&#xff1a;在运行代码过程中突然掉线&#xff0c;然后自动连线后使用su登录root失败&#xff0c;并且sudo失效 ubuntuLAPTOP-3II6MIRG:/mnt/c/Windows/system32$ su Password: Ubuntu …

数组翻转(C++)

对于一副扑克牌&#xff0c;我们有多种不同的洗牌方式。一种方法是从中间某个位置分成两半&#xff0c;然后相交换&#xff0c;我们称之为移位&#xff08;shift&#xff09;。 比如原来的次序是 123456&#xff0c;从第 4 个位置交换&#xff0c;结果就是 561234。 这个方式其…

使用opencv把视频转换为灰色并且逐帧率转换为图片

功能介绍 使用opencv库把视频转换为灰色&#xff0c;并且逐帧率保存为图片到本地 启动结果 整体代码 import cv2 import osvc cv2.VideoCapture(test.mp4)if vc.isOpened():open, frame vc.read() else:open Falseos.makedirs("grayAll", exist_okTrue) i 0 wh…

冻结Prompt微调LM: T5 PET (a)

T5 paper: 2019.10 Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer Task: Everything Prompt: 前缀式人工prompt Model: Encoder-Decoder Take Away: 加入前缀Prompt&#xff0c;所有NLP任务都可以转化为文本生成任务 T5论文的初衷如…

智慧景区售票系统

随着智能科技的不断发展&#xff0c;智慧景区综合售票管理系统成为了现代化旅游业不可或缺的一部分。本文将为您推荐中顶售票管理系统&#xff0c;让您更好地了解如何利用智慧科技提升景区售票管理效率。 智慧科技助力景区管理 中顶售票管理系统是一款基于智能科技的综合销售管…

Git项目分支管理规范

一、分支管理 创建项目时&#xff0c;会针对不同环境创建两个常设分支(也可以算主分支&#xff0c;永久不会删除) master&#xff1a;生产环境的稳定分支&#xff0c;生产环境基于该分支构建。仅用来发布新版本&#xff0c;除了从release测试分支或 hotfix-*Bug修复分支进行m…

阿里云服务器地域所在位置的详细解释

2024年阿里云服务器地域分布表&#xff0c;地域指数据中心所在的地理区域&#xff0c;通常按照数据中心所在的城市划分&#xff0c;例如华北2&#xff08;北京&#xff09;地域表示数据中心所在的城市是北京。阿里云地域分为四部分即中国、亚太其他国家、欧洲与美洲和中东&…

使用Matplotlib绘制3d图形

目录 一&#xff1a;绘制一个正方体 二&#xff1a;绘制一个3*3*3魔方 为了绘制立体&#xff0c;主要用到Matplotlib中的一个函数voxels voxels([x, y, z, ], filled, facecolorsNone, edgecolorsNone, **kwargs) 绘制一组填充体素&#xff0c;所有体素在坐标轴上绘制为1x1x…

ARM 1.12

norflash与nandflash的区别&#xff1a; 一、NAND flash和NOR flash的性能比较 1、NOR的读速度比NAND稍快一些。 2、NAND的写入速度比NOR快很多。 3、NAND的4ms擦除速度远比NOR的5s快。 4、大多数写入操作需要先进行擦除操作。 5、NAND的擦除单元更小&#xff0c;相应的擦除电…

windows11+GPU1060安装强化学习环境之pytorch

这里大家看一个视频系列&#xff0c;讲得非常详细&#xff0c;链接在此&#xff1a;https://www.bilibili.com/video/BV1S5411X7FY?p28&vd_source3be739b673e1151850f4b8060ac78e1a 这里主要是说我遇到的问题以及解决办法。 首先&#xff0c;我的笔记本是有显卡的&#xf…

来来来 这份强化学习(Reinforcement Learning)知识点秘籍请收好

Look&#xff01;&#x1f440;我们的大模型商业化落地产品&#x1f4d6;更多AI资讯请&#x1f449;&#x1f3fe;关注Free三天集训营助教在线为您火热答疑&#x1f469;&#x1f3fc;‍&#x1f3eb; 强化学习(RL)是机器学习的一个分支&#xff0c;重点是训练算法通过与环境的…

Spring MVC学习之——RequestMapping注解

RequestMapping注解 作用 用于建立请求URL和处理请求方法之间的对应关系。 属性 value&#xff1a;指定请求的实际地址&#xff0c;可以是一个字符串或者一个字符串列表。 value可以不写&#xff0c;直接在括号中写&#xff0c;默认就是value值 RequestMapping(value“/hel…

PXE——高效批量网络装机

目录 部署PXE远程安装服务 1.PXE概述 2.实现过程 3.实验操作 3.1安装dhcp、vsftpd、tftp-server.x86_64、syslinux服务 3.2修改配置文件——DHCP 3.3修改配置文件——TFTP 3.4kickstart——无人值守安装 3.4.1选择程序 3.4.2修改基础配置 3.4.3修改安装方法 3.4.4…

【开源】基于JAVA语言的快乐贩卖馆管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 搞笑视频模块2.3 视频收藏模块2.4 视频评分模块2.5 视频交易模块2.6 视频好友模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 搞笑视频表3.2.2 视频收藏表3.2.3 视频评分表3.2.4 视频交易表 四、系…

【Git相关问题】修改代码提交push时的用户名字

最简方法如下&#xff1a; 直接修改Git的用户配置文件 .gitconfig&#xff0c;这个配置文件的路径一般是 C:\Users\本机用户名\.gitconfig 用记事本或编辑器打开&#xff0c;在[user]下即可修改用户名name或邮箱email 参考&#xff1a; 使用Git进行版本控制&#xff0c;不同…