掌握 JavaScript 和 Java 中的二分搜尋:逐步指南
二分搜尋是每個開發人員都應該理解的基本演算法,它提供了一種高效的方法來搜尋排序數組中的元素。該演算法依賴於「分而治之」的方法,允許每一步將搜尋空間減半。在本文中,我們將探索 JavaScript 和 Java 中的二分搜索,涵蓋迭代和遞歸實作。
什麼是二分查找?
二分搜尋是一種旨在尋找排序數組中目標值的位置的演算法。透過利用陣列的排序特性,二分搜尋有效地縮小了搜尋空間,實現了 O(log n) 的時間複雜度。這比大型資料集中的線性搜尋快得多。
以下是進階概述:
- 以兩個指標開始,startIndex 和 endIndex,代表目前搜尋範圍。
- 計算startIndex和endIndex之間的中間索引(midIndex)。
- 將中間元素與目標進行比較:
- 如果與目標匹配,則返回索引。
- 如果中間元素大於目標,則目標一定在左半部分,所以調整endIndex。
- 如果中間元素小於目標,則目標一定在右半部分,所以調整startIndex。
- 重複這個過程,直到找到目標或startIndex超過endIndex,表示目標不在陣列中。
讓我們深入研究程式碼範例。
JavaScript 和 Java 中的迭代二分搜尋
JavaScript 實作
在 JavaScript 中,迭代方法使用迴圈來執行二分搜尋。它看起來像這樣:
const binarySearch = (arr, target) => { let startIndex = 0; let endIndex = arr.length - 1; while (startIndex <= endIndex) { let midIndex = Math.floor((startIndex + endIndex) / 2); if (arr[midIndex] === target) { return midIndex; // Target found } else if (arr[midIndex] < target) { startIndex = midIndex + 1; // Search in the right half } else { endIndex = midIndex - 1; // Search in the left half } } return -1; // Target not found }; let nums = [-1, 0, 3, 5, 9, 12]; console.log(binarySearch(nums, 9)); // Output: 4 console.log(binarySearch(nums, 2)); // Output: -1
Java實作
在Java中,迭代實作非常相似,只是Java語法有所調整:
public class BinarySearchExample { public static int binarySearch(int[] arr, int target) { int startIndex = 0; int endIndex = arr.length - 1; while (startIndex <= endIndex) { int midIndex = (startIndex + endIndex) / 2; if (arr[midIndex] == target) { return midIndex; // Target found } else if (arr[midIndex] < target) { startIndex = midIndex + 1; // Search in the right half } else { endIndex = midIndex - 1; // Search in the left half } } return -1; // Target not found } public static void main(String[] args) { int[] nums = {-1, 0, 3, 5, 9, 12}; int target = 9; int result = binarySearch(nums, target); if (result != -1) { System.out.println("Element found at index: " + result); } else { System.out.println("Element not found in the array."); } } }
解釋
在兩種實作中:
- 我們分別將 startIndex 和 endIndex 設定為陣列的開頭和結尾。
- 每次迭代都會找到中間索引 midIndex,並將 arr[midIndex] 與目標進行比較。
- 如果 arr[midIndex] 等於 target,我們回傳 midIndex。
- 如果 arr[midIndex] 小於 target,我們將 startIndex 移到 midIndex 1,將搜尋範圍縮小到右半部。
- 如果 arr[midIndex] 大於 target,我們將 endIndex 移到 midIndex - 1,將搜尋範圍縮小到左半部。
- 如果 startIndex 超過 endIndex,則循環退出,這表示目標不在陣列中。
JavaScript 和 Java 中的遞歸二分搜尋
對於遞歸方法,我們定義函數,以便它使用更新的索引來呼叫自身,直到找到目標或搜尋範圍為空。
JavaScript 實作
在 JavaScript 中,這是一個遞歸二分搜尋實作:
const binarySearch = (arr, target) => { let startIndex = 0; let endIndex = arr.length - 1; while (startIndex <= endIndex) { let midIndex = Math.floor((startIndex + endIndex) / 2); if (arr[midIndex] === target) { return midIndex; // Target found } else if (arr[midIndex] < target) { startIndex = midIndex + 1; // Search in the right half } else { endIndex = midIndex - 1; // Search in the left half } } return -1; // Target not found }; let nums = [-1, 0, 3, 5, 9, 12]; console.log(binarySearch(nums, 9)); // Output: 4 console.log(binarySearch(nums, 2)); // Output: -1
Java實作
在Java中,類似的遞歸二分查找可以實現如下:
public class BinarySearchExample { public static int binarySearch(int[] arr, int target) { int startIndex = 0; int endIndex = arr.length - 1; while (startIndex <= endIndex) { int midIndex = (startIndex + endIndex) / 2; if (arr[midIndex] == target) { return midIndex; // Target found } else if (arr[midIndex] < target) { startIndex = midIndex + 1; // Search in the right half } else { endIndex = midIndex - 1; // Search in the left half } } return -1; // Target not found } public static void main(String[] args) { int[] nums = {-1, 0, 3, 5, 9, 12}; int target = 9; int result = binarySearch(nums, target); if (result != -1) { System.out.println("Element found at index: " + result); } else { System.out.println("Element not found in the array."); } } }
遞歸版本如何運作
在每次遞迴呼叫中:
- 計算中間索引 midIndex。
- 如果 arr[midIndex] 與目標匹配,則傳回索引。
- 如果 arr[midIndex] 大於目標,則在左半部繼續搜尋(endIndex 變成 midIndex - 1)。
- 如果 arr[midIndex] 小於目標,則在右半部繼續搜尋(startIndex 變成 midIndex 1)。
- 基本情況 if (startIndex > endIndex) 確保在未找到目標時遞歸停止。
複雜性分析
- 時間複雜度:迭代和遞歸版本的時間複雜度均為 O(log n),因為每一步都會將搜尋空間減半。
- 空間複雜度:迭代方法的空間複雜度為 O(1),而遞歸方法由於呼叫堆疊的原因,空間複雜度為 O(log n)。
何時使用二分查找
二分搜尋在以下情況下是理想的選擇:
- 陣列已排序:二分查找僅適用於排序數組。
- 效率至關重要:其 O(log n) 時間複雜度對於大型資料集來說非常有效率。
如果數組未排序,請考慮先對其進行排序(以 O(n log n) 成本),或者如果資料集較小,則使用線性搜尋。
結論
二分搜尋是一種通用且高效的演算法,用於在排序數組中定位元素。無論您選擇迭代還是遞歸方法,了解二分搜尋對於提高應用程式的效能都很有價值。嘗試 JavaScript 和 Java 中的兩種實現,了解它們的工作原理,並查看哪種最適合您的特定用例。
?參考
- 二分查找
- Grouking 演算法
- 大 O 表示法
?跟我說話
- 領英
- Github
- 投資組合
以上是掌握 JavaScript 和 Java 中的二分搜尋:逐步指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undress AI Tool
免費脫衣圖片

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Java使用包裝類是因為基本數據類型無法直接參與面向對像操作,而實際需求中常需對象形式;1.集合類只能存儲對象,如List利用自動裝箱存儲數值;2.泛型不支持基本類型,必須使用包裝類作為類型參數;3.包裝類可表示null值,用於區分未設置或缺失的數據;4.包裝類提供字符串轉換等實用方法,便於數據解析與處理,因此在需要這些特性的場景下,包裝類不可或缺。

HashMap與Hashtable的區別主要體現在線程安全、null值支持及性能方面。 1.線程安全方面,Hashtable是線程安全的,其方法大多為同步方法,而HashMap不做同步處理,非線程安全;2.null值支持上,HashMap允許一個null鍵和多個null值,Hashtable則不允許null鍵或值,否則拋出NullPointerException;3.性能方面,HashMap因無同步機制效率更高,Hashtable因每次操作加鎖性能較低,推薦使用ConcurrentHashMap替

JIT編譯器通過方法內聯、熱點檢測與編譯、類型推測與去虛擬化、冗餘操作消除四種方式優化代碼。 1.方法內聯減少調用開銷,將頻繁調用的小方法直接插入調用處;2.熱點檢測識別高頻執行代碼並集中優化,節省資源;3.類型推測收集運行時類型信息實現去虛擬化調用,提升效率;4.冗餘操作消除根據運行數據刪除無用計算和檢查,增強性能。

StaticmethodsininterfaceswereintroducedinJava8toallowutilityfunctionswithintheinterfaceitself.BeforeJava8,suchfunctionsrequiredseparatehelperclasses,leadingtodisorganizedcode.Now,staticmethodsprovidethreekeybenefits:1)theyenableutilitymethodsdirectly

實例初始化塊在Java中用於在創建對象時運行初始化邏輯,其執行先於構造函數。它適用於多個構造函數共享初始化代碼、複雜字段初始化或匿名類初始化場景,與靜態初始化塊不同的是它每次實例化時都會執行,而靜態初始化塊僅在類加載時運行一次。

InJava,thefinalkeywordpreventsavariable’svaluefrombeingchangedafterassignment,butitsbehaviordiffersforprimitivesandobjectreferences.Forprimitivevariables,finalmakesthevalueconstant,asinfinalintMAX_SPEED=100;wherereassignmentcausesanerror.Forobjectref

類型轉換有兩種:隱式和顯式。 1.隱式轉換自動發生,如將int轉為double;2.顯式轉換需手動操作,如使用(int)myDouble。需要類型轉換的情況包括處理用戶輸入、數學運算或函數間傳遞不同類型的值時。需要注意的問題有:浮點數轉整數會截斷小數部分、大類型轉小類型可能導致數據丟失、某些語言不允許直接轉換特定類型。正確理解語言的轉換規則有助於避免錯誤。

工廠模式用於封裝對象創建邏輯,使代碼更靈活、易維護、松耦合。其核心答案是:通過集中管理對象創建邏輯,隱藏實現細節,支持多種相關對象的創建。具體描述如下:工廠模式將對象創建交給專門的工廠類或方法處理,避免直接使用newClass();適用於多類型相關對象創建、創建邏輯可能變化、需隱藏實現細節的場景;例如支付處理器中通過工廠統一創建Stripe、PayPal等實例;其實現包括工廠類根據輸入參數決定返回的對象,所有對象實現共同接口;常見變體有簡單工廠、工廠方法和抽象工廠,分別適用於不同複雜度的需求。
