關(guān)于二分法查找Java的實(shí)現(xiàn)及解析
二分法查找
概述
二分查找也稱(chēng)折半查找(Binary Search),它是一種效率較高的查找方法。
但是,折半查找要求線(xiàn)性表必須采用順序存儲(chǔ)結(jié)構(gòu),而且表中元素按關(guān)鍵字有序排列。
歸并排序即運(yùn)用了二分法的思想。首先需要一個(gè)由小到大排序好的數(shù)組,先對(duì)比中間的值,如果比要找的大,則向前找,取中間值前面的一半再找中間值再對(duì)比。
如果比要找的小,則向后找,取中間值后面的一半再取中間值再對(duì)比。
遞歸實(shí)現(xiàn)
這里,我使用了遞歸的方法進(jìn)行實(shí)現(xiàn)。
首先需要確認(rèn)查找的范圍,即有一個(gè)左索引和右索引,每次取(left+right)/2為中間值,比較要查找的元素和中間值的大小,若中間值大,則向前找,即遞歸范圍為left ,mid-1。反之向右找,即遞歸范圍mid+1,right。若相等即為找到。
但是需要繼續(xù)向此索引的前后找找看有沒(méi)有和其相等的值,一并加入到集合中,最后返回這個(gè)集合。
遞歸實(shí)現(xiàn)代碼
package search; import java.util.ArrayList; import java.util.List; public class BinarySearch { public static void main(String[] args) { int[] array = {1,1,1,2,3,4,5,6,7}; List<Integer> integers = binarySearch(array, 0, array.length - 1, 1); // for (Integer integer : integers) { // System.out.print(integer+ " "); // } System.out.println(integers); } public static List<Integer> binarySearch(int[] array, int left, int right, int value){ //如果左索引大于右索引,則說(shuō)明全部遍歷完了,也沒(méi)有找到相應(yīng)的值,返回空集合即可 if (left>right){ return new ArrayList<Integer>(); } //獲取中間值的下標(biāo)(二分) int mid = (left+right)/2; //如果要找的值比中間值小,則繼續(xù)向左找 if (value < array[mid]){ return binarySearch(array, left, mid-1, value); //要找的值比中間值小大,則向右找 }else if (value > array[mid]){ return binarySearch(array, mid+1, right, value); //否則,說(shuō)明相等,找到了 }else { //找到一個(gè),還需要向左右找找看有沒(méi)有相同的值 List<Integer> resultList = new ArrayList(); //向左循環(huán)找,如果有,則加入到集合中 int temp = mid - 1; while (temp>=0 && array[temp] == value){ resultList.add(temp); temp -= 1; } //向右循環(huán)找,如果有,則加入到集合中 temp = mid + 1; while (temp < array.length && array[temp] == value){ resultList.add(temp); temp += 1; } //將一開(kāi)始找到的那個(gè)索引頁(yè)加入到集合中。 resultList.add(mid); return resultList; } } //以下這段代碼來(lái)自百度百科,供大家參考。 public static int binarySearch(Integer[] srcArray, int des) { //定義初始最小、最大索引 int start = 0; int end = srcArray.length - 1; //確保不會(huì)出現(xiàn)重復(fù)查找,越界 while (start <= end) { //計(jì)算出中間索引值 int middle = (end + start)>>>1 ;//防止溢出 if (des == srcArray[middle]) { return middle; //判斷下限 } else if (des < srcArray[middle]) { end = middle - 1; //判斷上限 } else { start = middle + 1; } } //若沒(méi)有,則返回-1 return -1; } }
循環(huán)實(shí)現(xiàn)代碼(非遞歸)
package search; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @Author: sshdg * @Date: 2020/9/21 9:22 */ public class BinarySearch2 { public static void main(String[] args) { int[] array = {1,1,1,1,1,2,3,4,5,6,7}; System.out.println(BinarySearch2.binarySearch(array, 7)); } public static List<Integer> binarySearch(int[] array, int key){ List<Integer> resultList = new ArrayList<>(); int start = 0; int end = array.length - 1; while (start <= end){ int mid = (start + end) / 2; int midValue = array[mid]; if (key > midValue){ //key比中間值大。向右找 start = mid + 1; } else if (key < midValue){ //key比中間值小。向左找 end = mid - 1; } else { //否則就找到了 //先向左找有沒(méi)有相同值 int temp = mid -1; while (temp >= start && array[temp] == key){ resultList.add(temp); temp -= 1; } //將一開(kāi)始找到的加入結(jié)果集 resultList.add(mid); //再向右找找有沒(méi)有相同值 temp = mid + 1; while (temp <= end && array[temp] == key){ resultList.add(temp); temp += 1; } break; } } return resultList; } }
二分法查找(遞歸、循環(huán))
public class BinarySearch { /** * @author JadeXu * @// TODO: 2020/12/7 二分查找 * 思路: * 1、獲取數(shù)組的中間值,先獲取下標(biāo),方便多次查找 * 奇數(shù)位的數(shù)組直接獲取中間位,偶數(shù)位的數(shù)組獲取中間的第一位或第二位都可,一般獲取第一位(因?yàn)榕c奇數(shù)位獲取中間值的方法一樣) * 2、獲取查找的區(qū)間范圍,start:區(qū)間開(kāi)始的下標(biāo),end:區(qū)間結(jié)束的下標(biāo) * 3、判斷查找的數(shù)和中間位的數(shù)是否相同 * 相同時(shí),直接返回需要的數(shù)據(jù),跳出方法 * 大于時(shí),即數(shù)可能在中間值右邊的區(qū)間內(nèi),此時(shí)start = mid+1,即mid往后移一位,就得到了中間值右邊區(qū)間的開(kāi)始下標(biāo) * 小于時(shí),即數(shù)可能在中間值左邊的區(qū)間內(nèi),此時(shí)end = mid-1,即mid往前移一位,就得到了中間值左邊區(qū)間的結(jié)束下標(biāo) * 當(dāng)一個(gè)區(qū)間里,開(kāi)始下標(biāo)小于等于結(jié)束下標(biāo)時(shí),該區(qū)間才是有效區(qū)間,才能繼續(xù)查找。否則無(wú)效,返回找不到,跳出方法 */ //循環(huán) /** * @param arr 已經(jīng)升序好的int[] * @param num 需要查找的數(shù)字 * @return 找到則返回下標(biāo),沒(méi)找到則返回-1 */ private static int binarySearchByCycle(int[] arr,int num) { int start = 0; int end = arr.length - 1; while (start <= end){ int mid = (start + end) / 2; if(num == arr[mid]){ return mid; }else if(num > arr[mid]){ start = mid + 1; }else { end = mid - 1; } } return -1; } //遞歸 /** * @param arr 已經(jīng)升序好的int[] * @param num 需要查找的數(shù)字 * @param start 區(qū)間開(kāi)始下標(biāo) * @param end 區(qū)間結(jié)束下標(biāo) * @return 找到則返回下標(biāo),沒(méi)找到則返回-1 */ private static int binarySearchByRecursion(int[] arr,int num,int start,int end) { int mid = (start + end) / 2; if(num == arr[mid]){ return mid; }else if(num > arr[mid]){ start = mid + 1; }else { end = mid - 1; } if(start <= end){ mid = binarySearchByRecursion(arr,num,start,end); //遞歸繼續(xù)尋找 }else { mid = -1; } return mid; } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot啟動(dòng)過(guò)程(四)之Spring Boot內(nèi)嵌Tomcat啟動(dòng)
這篇文章主要介紹了Spring Boot啟動(dòng)過(guò)程(四)之Spring Boot內(nèi)嵌Tomcat啟動(dòng)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-04-04SpringBoot如何通過(guò)配置禁用swagger
這篇文章主要給大家介紹了關(guān)于SpringBoot如何通過(guò)配置禁用swagger的相關(guān)資料,Swagger用來(lái)在開(kāi)發(fā)階段方便前后端分離的項(xiàng)目實(shí)戰(zhàn)中,提高前后端人員的工作效率,降低交流成本,但是版本上線(xiàn)之后要是把Swagger帶上去會(huì)存在很大的風(fēng)險(xiǎn),需要的朋友可以參考下2023-08-08消息隊(duì)列-kafka消費(fèi)異常問(wèn)題
這篇文章主要給大家介紹了關(guān)于kafka的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07基于spring?@Cacheable?注解的spel表達(dá)式解析執(zhí)行邏輯
這篇文章主要介紹了spring?@Cacheable?注解的spel表達(dá)式解析執(zhí)行邏輯,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Java反射通過(guò)Getter方法獲取對(duì)象VO的屬性值過(guò)程解析
這篇文章主要介紹了Java反射通過(guò)Getter方法獲取對(duì)象VO的屬性值過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02springboot整合shiro登錄失敗次數(shù)限制功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了springboot整合shiro-登錄失敗次數(shù)限制功能,實(shí)現(xiàn)此功能如果是防止壞人多次嘗試,破解密碼的情況,所以要限制用戶(hù)登錄嘗試次數(shù),需要的朋友可以參考下2018-09-09Spring動(dòng)態(tài)配置計(jì)時(shí)器觸發(fā)時(shí)間的實(shí)例代碼
這篇文章主要介紹了Spring動(dòng)態(tài)配置計(jì)時(shí)器觸發(fā)時(shí)間的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-06-06