1. 使用闭区间,初始化 start = 0, end = n-1。
2. 循环条件 while (start <= end)
3. 中间元素的取法: int mid = low + ((high - low) / 2);
一段典型的code:
1: public static int binarySearch(int[] a, int key) { 2: int low = 0; 3: int high = a.length - 1; 4: 5: while (low <= high) { 6: int mid = low + (high-low) / 2; 7: int midVal = a[mid]; 8: 9: if (midVal < key) 10: low = mid + 1 11: else if (midVal > key) 12: high = mid - 1; 13: else 14: return mid; // key found 15: } 16: return -1; // key not found. 17: }
Leetcode 相关题目: Search for a Range, Search in Rotated Sorted Array, Search in Rotated Sorted Array II
Leetcode: Search in Rotated Sorted Array 代码:
4. 边界条件。当end-start = 1时,注意mid = start,此时如果A[start]不符合条件,应该转向start = mid+1,搜索第二个元素,而如果end = mid-1,则直接退出循环而发生错误。
直观来看,如果int mid = low + ((high - low) / 2); 则应将 if(A[start] < A[mid])和 if(A[start] == A[mid])合并为一种情况来处理(都应搜索后半部分)。
如果int mid = low + ((high - low +1) / 2); 应将if(A[mid] < A[end])和 if(A[end] == A[mid]) 合并为一种情况(都应搜索前半部分)。
class Solution {
public:
int search(int A[], int n, int target)
{
if(n == 0) return -1;
//if(n == 1) return A[0] == target?0:-1;
int start = 0, end = n-1;
while(start <= end)
{
int mid = start + (end - start)/2;
if(A[mid] == target) return mid;
if(A[start] <= A[mid])
{
if(A[start] <= target && target < A[mid])
end = mid-1;
else
start = mid+1;
}
else
{
if(A[mid] < target && target <= A[end])
start = mid+1;
else
end = mid-1;
}
}
return -1;
}
};
Leetcode: Search in Rotated Sorted Array II 代码:
class Solution {
public:
bool search(int A[], int n, int target) {
if(n == 0) return false;
int start = 0, end = n-1;
while(start <= end)
{
int mid = start + (end - start)/2;
if(A[mid] == target) return true;
if(A[start] < A[mid])
{
if(A[start] <= target && target < A[mid])
end = mid-1;
else
start = mid+1;
}
else if(A[start] > A[mid])
{
if(A[mid] < target && target <= A[end])
start = mid+1;
else
end = mid-1;
}
if(A[start] == A[mid])
start++;
if(A[mid] == A[end])
end--;
}
return false;
}
};
题目: Find the minimum element in a sorted and rotated array
http://www.geeksforgeeks.org/find-minimum-element-in-a-sorted-and-rotated-array/
int findMin(int arr[], int n)
{
int low = 0;
int high = n-1;
if(n == 1) return arr[0];
while (low <= high)
{
// Find mid
int mid = low + (high - low)/2;
if(mid-1 >= 0 && arr[mid-1] > arr[mid])
return arr[mid];
if(mid+1 < n && arr[mid] > arr[mid+1])
return arr[mid+1];
if(arr[low] <= arr[mid])
low = mid + 1;
else
low = mid - 1;
}
return arr[0];
}
// Driver program to test above functions
int main()
{
int arr1[] = {5, 6, 1, 2, 3, 4};
int n1 = sizeof(arr1)/sizeof(arr1[0]);
printf("The minimum element is %d\n", findMin(arr1, n1));
int arr2[] = {1, 2, 3, 4};
int n2 = sizeof(arr2)/sizeof(arr2[0]);
printf("The minimum element is %d\n", findMin(arr2, n2));
int arr3[] = {1};
int n3 = sizeof(arr3)/sizeof(arr3[0]);
printf("The minimum element is %d\n", findMin(arr3, n3));
int arr4[] = {1, 2};
int n4 = sizeof(arr4)/sizeof(arr4[0]);
printf("The minimum element is %d\n", findMin(arr4, n4));
int arr5[] = {2, 1};
int n5 = sizeof(arr5)/sizeof(arr5[0]);
printf("The minimum element is %d\n", findMin(arr5, n5));
int arr6[] = {5, 6, 7, 1, 2, 3, 4};
int n6 = sizeof(arr6)/sizeof(arr6[0]);
printf("The minimum element is %d\n", findMin(arr6, n6));
int arr7[] = {1, 2, 3, 4, 5, 6, 7};
int n7 = sizeof(arr7)/sizeof(arr7[0]);
printf("The minimum element is %d\n", findMin(arr7, n7));
int arr8[] = {2, 3, 4, 5, 6, 7, 8, 1};
int n8 = sizeof(arr8)/sizeof(arr8[0]);
printf("The minimum element is %d\n", findMin(arr8, n8));
int arr9[] = {3, 4, 5, 1, 2};
int n9 = sizeof(arr9)/sizeof(arr9[0]);
printf("The minimum element is %d\n", findMin(arr9, n9));
return 0;
}
有重复元素的情况:
class Solution {
public:
int findMin(vector<int> &arr) {
const int n = arr.size();
<span style="white-space:pre"> </span>int low = 0;
<span style="white-space:pre"> </span>int high = n-1;
<span style="white-space:pre"> </span>if(n == 1) return arr[0];
<span style="white-space:pre"> </span>while (low <= high)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span> // Find mid
<span style="white-space:pre"> </span> int mid = low + (high - low)/2;
<span style="white-space:pre"> </span> if(mid-1 >= 0 && arr[mid-1] > arr[mid])
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>return arr[mid];
<span style="white-space:pre"> </span> if(mid+1 < n && arr[mid] > arr[mid+1])
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>return arr[mid+1];
if(arr[mid] < arr[high])
high = mid-1;
else if(arr[mid] > arr[high])
low = mid+1;
else
high--;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return arr[0];
}
};
总结: 这两个题目中,如果元素有重复,只能利用以下代码段,逐一跳过重复元素。运行时间介于O(logN)和O(n)之间。
if(arr[low] == arr[mid])
low++;
else if(arr[mid] == arr[high])
high--;