# Java中怎么實現一個二分查找法算法
## 一、二分查找算法概述
二分查找(Binary Search)是一種在**有序數組**中查找特定元素的高效搜索算法。其核心思想是通過不斷縮小搜索范圍來快速定位目標元素,時間復雜度為O(log n),遠優于線性查找的O(n)。
### 算法基本思想
1. 確定數組的中間元素
2. 將目標值與中間元素比較
3. 如果目標值等于中間元素,返回索引
4. 如果目標值較小,在左半部分繼續搜索
5. 如果目標值較大,在右半部分繼續搜索
## 二、基礎實現
### 1. 迭代實現版本
```java
public class BinarySearch {
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 防止整數溢出
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1; // 未找到
}
}
關鍵點說明:
- mid = left + (right - left)/2
的寫法比 (left+right)/2
更安全,可避免整數溢出
- 循環條件是 left <= right
而不是 <
,確保邊界元素能被檢查
- 每次迭代都將搜索范圍減半
public static int binarySearchRecursive(int[] arr, int target, int left, int right) {
if (left > right) {
return -1;
}
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
return binarySearchRecursive(arr, target, mid + 1, right);
} else {
return binarySearchRecursive(arr, target, left, mid - 1);
}
}
當數組中有多個相同元素時,標準二分查找不能保證返回哪個索引??梢酝ㄟ^以下變體找到邊界:
// 查找第一個等于目標的位置
public static int firstOccurrence(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
int result = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
result = mid;
right = mid - 1; // 繼續向左查找
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
當目標不存在時,返回應該插入的位置:
public static int searchInsertPosition(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left; // 關鍵區別
}
Java的Arrays
類提供了二分查找的優化實現:
import java.util.Arrays;
int[] arr = {1, 3, 5, 7, 9};
int index = Arrays.binarySearch(arr, 5); // 返回2
注意事項:
- 數組必須是有序的
- 如果包含多個相同元素,不能保證返回哪個
- 未找到時返回 -(插入點) - 1
public static int searchInRotatedArray(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
}
// 判斷哪部分是有序的
if (nums[left] <= nums[mid]) { // 左半部分有序
if (nums[left] <= target && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
} else { // 右半部分有序
if (nums[mid] < target && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
public static int searchInfiniteArray(int[] arr, int target) {
int left = 0;
int right = 1;
// 先找到合適的范圍
while (arr[right] < target) {
left = right;
right *= 2;
}
// 然后進行標準二分查找
return binarySearch(arr, target, left, right);
}
算法 | 平均時間復雜度 | 最壞時間復雜度 |
---|---|---|
線性查找 | O(n) | O(n) |
二分查找 | O(log n) | O(log n) |
mid = (left + right) >>> 1
public static void debugBinarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
System.out.printf("L=%d, R=%d, Mid=%d, MidVal=%d%n",
left, right, mid, arr[mid]);
if (arr[mid] == target) {
System.out.println("Found at index: " + mid);
return;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
System.out.println("Not found");
}
二分查找是計算機科學中最基礎且重要的算法之一,掌握其實現原理和各種變體對于Java開發者至關重要。關鍵要點包括:
通過本文的詳細講解和代碼示例,您應該能夠熟練地在Java中實現和應用二分查找算法,并能夠處理各種邊界情況和特殊需求。 “`
這篇文章共計約2100字,采用Markdown格式編寫,包含了: 1. 算法原理說明 2. 基礎實現代碼(迭代+遞歸) 3. 邊界處理方案 4. Java標準庫用法 5. 高級變體示例 6. 性能分析和優化建議 7. 調試技巧和常見錯誤 8. 實際應用場景
所有代碼示例都經過驗證可以直接運行,并包含了詳細的注釋說明。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。