算法-05-二分查找

二分查找(Binary Search)算法,也叫折半查找算法,是一種針對有序數據集合的查找算法。

1-二分查找的思想

? ? ? ? 我們生活中猜數字的游戲,告訴你一個數據范圍,比如0-100,然后你說出一個數字,我告訴你的目標數字比你的大還是小,你繼續猜,根據二分查找的思想,你只要幾次就可以猜中。比如目標值68。

每次猜一個數字,通過告知結果后,排除掉一半的數字,這種思想就是二分查找。

? ? ? 二分查找針對的是一個有序的數據集合,查找思想有點類似分治思想。每次都通過跟區間的中間元素對比,將待查找的區間縮小為之前的一半,直到找到要查找的元素,或者區間被縮小為0

? ? ? 折半的思想從而使得二分查找的時間復雜度是O(logn)。這是一種極其高效的時間復雜度;因為logn是一個非常“恐怖”的數量級,即便n非常非常大,對應的logn也很小。比如n等于2的32次方,大約是42億。也就是說,如果我們在42億個數據中用二分查找一個數據,最多需要比較32次。

2-二分查找實現

? ? ? ?假設數組中不存在重復的元素(數組中的元素有序,并且從小到大排序好),查找數組中是否存在某個元素,存在就返回元素在數組中的下標;不存在就返回-1。

   /*** 查詢數組中等于 target 的 索引* 數組中沒有重復的元素** @param array  待查找的數組* @param target 目標值* @return 數組下標索引,沒有查詢到返回-1*/
private static int binarySearch01(int[] array, int target) {int low = 0;int high = array.length - 1;while (low <= high) {int mid = low + ((high - low) >> 1);if (array[mid] == target) {return mid;}if (array[mid] > target) {high = mid - 1;}if (array[mid] < target) {low = mid + 1;}}return -1;}

3-二分查找的特點

(1)二分查找依賴的是順序表結構,簡單點說就是數組。
(2)二分查找針對的是有序數據。
(3)數據量太小不適合二分查找。但是如果數據之間的比較操作非常耗時,不管數據量大小,我都推薦使用二分查找。比如,數組中存儲的都是長度超過300的字符串,如此長的兩個字符串之間比對大小,就會非常耗時。我們需要盡可能地減少比較次數,而比較次數的減少會大大提高性能,這個時候二分查找就比順序遍歷更有優勢。
(4)數據量太大也不適合二分查找。二分查找的底層需要依賴數組這種數據結構,而數組為了支持隨機訪問的特性,要求內存空間連續,對內存的要求比較苛刻。

4-二分查找的變形問題

4.1-查找第一個值等于給定值的元素

? ? ? 上面的二分查找算法中,要求數組中存在不重復的數字,現在我們取消這個限制,查找數組中第一個值等于給定值的元素。

    /*** 查詢數組中第一個等于target的數字,返回數組的索引** @param array  目前數組* @param target 目標值* @return 數組下標索引,沒有查詢到返回-1*/private static int binarySearch02(int[] array, int target) {int low = 0;int high = array.length - 1;while (low <= high) {int mid = low + ((high - low) >> 1);if (array[mid] == target) {if ((mid == 0) || array[mid - 1] != target) {return mid;} else {high = mid - 1;}}if (array[mid] > target) {high = mid - 1;}if (array[mid] < target) {low = mid + 1;}}return -1;}

? ? ? 如果mid等于0,那這個元素已經是數組的第一個元素,那它肯定是我們要找的;如果mid不等于0,但a[mid]的前一個元素a[mid-1]不等于value,那也說明a[mid]就是我們要找的第一個值等于給定值的元素。

4.2-查找最后一個值等于給定值的元素

? ? ? 要求數組中存在不重復的數字,現在我們取消這個限制,查找數組中最后一個值等于給定值的元素。

    /*** 查詢數組中最后一個等于target的數字,返回數組的索引** @param array  目前數組* @param target 目標值* @return 數組下標索引,沒有查詢到返回-1*/private static int binarySearch03(int[] array, int target) {int low = 0;int maxIndex = array.length - 1;int high = array.length - 1;while (low <= high) {int mid = low + ((high - low) >> 1);if (array[mid] == target) {if ((mid == maxIndex) || array[mid + 1] != target) {return mid;} else {low = mid + 1;}}if (array[mid] > target) {high = mid - 1;}if (array[mid] < target) {low = mid + 1;}}return -1;}

? ? ? ?如果a[mid]這個元素已經是數組中的最后一個元素了,那它肯定是我們要找的;如果a[mid]的后一個元素a[mid+1]不等于value,那也說明a[mid]就是我們要找的最后一個值等于給定值的元素。如果我們經過檢查之后,發現a[mid]后面的一個元素a[mid+1]也等于value,那說明當前的這個a[mid]并不是最后一個值等于給定值的元素。我們就更新low=mid+1,因為要找的元素肯定出現在[mid+1, high]之間。

4.3-查找第一個大于等于給定值的元素

? ? ? ?對于a[mid]大于等于給定值value的情況,我們要先看下這個a[mid]是不是我們要找的第一個值大于等于給定值的元素。如果a[mid]前面已經沒有元素,或者前面一個元素小于要查找的值value,那a[mid]就是我們要找的元素。如果a[mid-1]也大于等于要查找的值value,那說明要查找的元素在[low, mid-1]之間,所以,我們將high更新為mid-1。

  /*** 查詢數組中查找第一個大于等于給定值的元素,返回數組的索引** @param array  目前數組* @param target 目標值* @return 數組下標索引,沒有查詢到返回-1*/private static int binarySearch04(int[] array, int target) {int low = 0;int high = array.length - 1;while (low <= high) {int mid = low + ((high - low) >> 1);if (array[mid] >= target) {if ((mid == 0) || array[mid - 1] < target) {return mid;} else {high = mid - 1;}} else {low = mid + 1;}}return -1;}

4.4-查找最后一個小于等于給定值的元素

? ? ? ?對于a[mid]小于等于給定值value的情況,我們要先看下這個a[mid]是不是我們要找的最后一個值小于等于給定值的元素。如果a[mid]后面已經沒有元素,或者后面一個元素大于要查找的值value,那a[mid]就是我們要找的元素。如果a[mid+1]也小于等于要查找的值value,那說明要查找的元素在[mid+1, high]之間,所以,我們將low更新為mid+1。

    /*** 查詢數組中查找最后一個小于等于給定值的元素,返回數組的索引** @param array  目前數組* @param target 目標值* @return 數組下標索引,沒有查詢到返回-1*/private static int binarySearch05(int[] array, int target) {int low = 0;int maxIndex = array.length - 1;int high = array.length - 1;while (low <= high) {int mid = low + ((high - low) >> 1);if (array[mid] <= target) {if ((mid == maxIndex) || array[mid + 1] > target) {return mid;} else {low = mid + 1;}}}return -1;}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215437.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215437.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215437.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

工業相機與鏡頭選型方法(含實例)

一、相機介紹及選型方法 1.工業相機介紹 工業相機與我們手機上面的相機或者我們單反相機不同,工業相機它能夠使用各種惡劣的工作環境,比如說高溫,高壓,高塵等。工業相機主要有面陣相機和線陣相機,線陣相機主要用于檢測精度要求很高,運動速度很快的場景,而面陣相機應用…

Leetcode刷題詳解——字符串中的第一個唯一字符

1. 題目鏈接&#xff1a;387. 字符串中的第一個唯一字符 2. 題目描述&#xff1a; 給定一個字符串 s &#xff0c;找到 它的第一個不重復的字符&#xff0c;并返回它的索引 。如果不存在&#xff0c;則返回 -1 。 示例 1&#xff1a; 輸入: s "leetcode" 輸出: 0示…

spring 屬性注入 @Autowired和@Resource注解使用

眾所周知Resource 和 Autowired兩大注解是開發中最常用的兩大注解。兩者有一定的區別&#xff1a; Autowired Autowired是spring框架提供的注解類&#xff0c;默認按照類型進行裝配。當在容器中找不到對應類型的bean時會拋出NoSuchBeanDefinitionException異常&#xff0c;當…

C語言中的結構體成員賦值與訪問詳解

C語言中的成員賦值與訪問 在C語言中&#xff0c;我們可以使用不同的方式對結構體變量的成員進行賦值和訪問。本文將詳細介紹這些方式&#xff0c;并通過具體的示例代碼加以說明。 目錄 使用strcpy_s函數賦值字符串直接賦值數字和浮點數結構體變量之間的賦值使用復合文字進行…

周周清(2)----踩坑日記

周一&#xff1a; 1.之前換了一個jdk&#xff0c;然后又改了很多東西&#xff0c;很亂&#xff0c;以至于很多項目都不能直接運行了&#xff0c;所以今天就將ideal刪除并且更新版本到2022.3.3&#xff0c;并且重新將ideal里面的配置環境變量&#xff0c;以及jdk下載安裝配置&a…

數據庫系列之簡要對比下GaussDB和OpenGauss數據庫

GaussDB作為一款企業級的數據庫產品&#xff0c;和開源數據庫OpenGauss之間又是什么樣的關系&#xff0c;剛開始接觸的時候是一頭霧水&#xff0c;因此本文簡要對比下二者的區別&#xff0c;以加深了解。 1、GaussDB和OpenGauss數據庫簡要對比 GaussDB是華為基于PostgreSQL數據…

WPF仿網易云搭建筆記(4):信息流控制之消息訂閱

文章目錄 專欄和Gitee倉庫前言消息訂閱最簡單的案例簡單用例父組件訂閱子組件回調 結果 消息訂閱機制消息token是A還是B?傳遞消息的載體。雙重token重復訂閱問題 結論 專欄和Gitee倉庫 WPF仿網易云 Gitee倉庫 WPF仿網易云 CSDN博客專欄 前言 上一篇文章中&#xff0c;我們簡單…

PHP基礎(1)

PHP是一種服務器端腳本語言&#xff0c;是一種用于開發動態Web應用程序的最流行和廣泛使用的語言之一。它的全稱為“Hypertext Preprocessor”&#xff0c;是一種開源的、可嵌入HTML的腳本語言&#xff0c;可以嵌入到HTML中&#xff0c;也可以直接作為命令行腳本運行。PHP腳本在…

Java小案例-如果您的 Java 應用程序在不做任何事情時正在消耗 CPU,您如何確定它在做什么?

前言 我正在調用供應商的 Java API&#xff0c;在某些服務器上&#xff0c;JVM 在登錄 API 后似乎進入了低優先級輪詢循環&#xff08;CPU 使用率為 100%&#xff09;。其他服務器上的同一應用程序不會出現此行為。這發生在 WebSphere 和 Tomcat 上。環境設置起來很棘手&#…

DevOps搭建(四)-GitLab安裝細步驟

在這里我們用docker安裝 1、創建gitlab安裝目錄 mkdir -p /usr/local/docker/gitlab_docker 進入該目錄 cd /usr/local/docker/gitlab_docker 2、下載gitlab鏡像 docker pull gitlab/gitlab-ce:latest 3、創建docker-compose.yml vi docker-compose.yml 輸入以下內容保…

理解 HTTP POST 請求:表單與 JSON 數據格式深入解析20231208

引言 在日常的 Web 開發中&#xff0c;理解 HTTP POST 請求的不同數據格式是至關重要的。這不僅有助于構建健壯的后端服務&#xff0c;還能確保與其他服務的有效溝通。本文將深入探討 multipart/form-data 和 application/json&#xff0c;這兩種常見的 POST 請求格式。 POST…

2023 年安徽省職業院校技能大賽高職組“軟件測試”賽項樣題

2023 年安徽省職業院校技能大賽 高職組“軟件測試”賽項樣題 目錄 任務一&#xff1a;功能測試&#xff08;45 分&#xff09; 1、測試計劃&#xff08;5 分&#xff09; 2、測試用例&#xff08;15 分&#xff09; 3、Bug 清單&#xff08;20 分&#xff09; 4、測試報告&…

Python 學習筆記之 networkx 使用

介紹 networkx networkx 支持創建簡單無向圖、有向圖和多重圖&#xff1b;內置許多標準的圖論算法&#xff0c;節點可為任意數據&#xff1b;支持任意的邊值維度&#xff0c;功能豐富&#xff0c;簡單易用 networkx 中的 Graph Graph 的定義 Graph 是用點和線來刻畫離散事物…

張馳咨詢:數據驅動的質量改進,六西格瑪綠帶在汽車業實踐

尊敬的汽車行業同仁們&#xff0c;您是否曾面臨生產效率低下、成本不斷攀升或顧客滿意度下降的困擾&#xff1f;本期專欄&#xff0c;我們將深入探討如何通過六西格瑪綠帶培訓&#xff0c;在汽車行業中實現過程優化和質量提升。 汽車行業的競爭日趨激烈&#xff0c;致力于提供…

3.cloud-Consul服務注冊與發現

1.官網 https://learn.hashicorp.com/consul/getting-started/install.html 2.訂單服務 2.1 POM <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependenc…

學習Java第66天,路徑問題

相對路徑情況分析 相對路徑情況1:web/index.html中引入web/static/img/logo.png 訪問index.html的url為 : http://localhost:8080/web03_war_exploded/index.html 當前資源為 : index.html 當前資源的所在路徑為 : http://localhost:8080/web03_war_exploded/ 要獲取的目標資…

【華為數據之道學習筆記】3-9元數據治理面臨的挑戰

華為在進行元數據治理以前&#xff0c;遇到的元數據問題主要表現為數據找不到、讀不懂、不可信&#xff0c;數據分析師們往往會陷入數據沼澤中&#xff0c;例如以下常見的場景。 某子公司需要從發貨數據里對設備保修和維保進行區分&#xff0c;用來不對過保設備進行服務場景分析…

Qt 使用百度的離線地圖

使用百度離線地圖&#xff0c;一下載百度離線包&#xff08;offlinemap&#xff09;&#xff1b;二是準備地圖瓦片&#xff08;不同級別的瓦片&#xff09;&#xff1b;三 準備&#xff48;&#xff54;&#xff4d;&#xff4c;主頁面&#xff1b;四&#xff0c;&#xff31;&…

深度學習 Day13——P2彩色圖片分類

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 | 接輔導、項目定制 文章目錄 前言1 我的環境2 代碼實現與執行結果2.1 前期準備2.1.1 引入庫2.1.2 設置GPU&#xff08;如果設備上支持GPU就使用GPU,否則使用C…

在Go中定義方法

引言 函數允許你將邏輯組織到可重復的過程中,每次運行時可以使用不同的參數。在定義函數的過程中,你會經常發現多個函數可能每次都操作同一段數據。Go可以識別這種模式,并允許您定義特殊的函數,稱為方法,其目的是對某些特定類型的實例進行操作,稱為接收器。為類型添加方…