二分查找及拓展
- 请快速写出二分查找的代码。
- 把一个数组最开始的若干个元素搬到数组的末尾,叫数组的旋转。输入一个递增排序的数组的一个旋转,输出数组的最小元素。(8)
- 统计一个数字在排序数组中出现的次数。(38)
1、思路:
要求输入数组是排序的,这样二分查找的算法是log(n)。
BinarySearch
1 int BinarySearch(int data[], int length, int key) 2 { 3 int low, high, mid; 4 low = 0; 5 high = length - 1; 6 while (low <= high) 7 { 8 mid = (low + high) / 2; 9 if (data[mid] == key) 10 return mid; 11 else if (data[mid] > key) 12 high = mid - 1; 13 else 14 low = mid + 1; 15 } 16 return -1; 17 }
2、思路:
设置首尾两个指针,首指针指向的数一定比尾指针指向的数要大。通过比较中间指针和首尾指针指向的数的大小,来移动首尾指针。最后首尾指针相邻,尾指针指向的就是最小数。
MinInRotate
1 int Min(int* numbers, int length) 2 { 3 if(numbers == NULL || length <= 0) 4 throw new std::exception("Invalid parameters"); 5 6 int index1 = 0; 7 int index2 = length - 1; 8 int indexMid = index1; 9 while(numbers[index1] >= numbers[index2]) 10 { 11 // 如果index1和index2指向相邻的两个数, 12 // 则index1指向第一个递增子数组的最后一个数字, 13 // index2指向第二个子数组的第一个数字,也就是数组中的最小数字 14 if(index2 - index1 == 1) 15 { 16 indexMid = index2; 17 break; 18 } 19 20 // 如果下标为index1、index2和indexMid指向的三个数字相等, 21 // 则只能顺序查找 22 indexMid = (index1 + index2) / 2; 23 if(numbers[index1] == numbers[index2] && numbers[indexMid] == numbers[index1]) 24 return MinInOrder(numbers, index1, index2); 25 26 // 缩小查找范围 27 if(numbers[indexMid] >= numbers[index1]) 28 index1 = indexMid; 29 else if(numbers[indexMid] <= numbers[index2]) 30 index2 = indexMid; 31 } 32 33 return numbers[indexMid]; 34 } 35 36 int MinInOrder(int* numbers, int index1, int index2) 37 { 38 int result = numbers[index1]; 39 for(int i = index1 + 1; i <= index2; ++i) 40 { 41 if(result > numbers[i]) 42 result = numbers[i]; 43 } 44 45 return result; 46 }
3、思路:
通过二分查找,找到那个数的起始位置和结束位置,这样个数就显而易见了。以求起始位置为例,只有保证mid指针指向该数,并且前一个指针指向的是其他的数,才算成功。
GetNumOfK
1 #include <stdio.h> 2 3 int GetFirstK(int* data, int k, int length) 4 { 5 if (data == NULL || length <= 0) return -1; 6 7 int low, high, mid; 8 low = 0; 9 high = length - 1; 10 while (low <= high) 11 { 12 mid = (low + high) / 2; 13 if (data[mid] == k) 14 { 15 if ((mid > 0 && data[mid - 1] != k) || mid == 0) 16 return mid; 17 else 18 high = mid - 1; 19 } 20 else if (data[mid] > k) 21 high = mid - 1; 22 else 23 low = mid + 1; 24 } 25 return -1; 26 } 27 28 int GetLastK(int* data, int k, int length) 29 { 30 if (data == NULL || length <= 0) return -1; 31 32 int low, high, mid; 33 low = 0; 34 high = length - 1; 35 while (low <= high) 36 { 37 mid = (low + high) / 2; 38 if (data[mid] == k) 39 { 40 if ((mid < length - 1 && data[mid + 1] != k) || mid == length - 1) 41 return mid; 42 else 43 high = mid - 1; 44 } 45 else if (data[mid] > k) 46 high = mid - 1; 47 else 48 low = mid + 1; 49 } 50 return -1; 51 } 52 53 int GetNumOfK(int *data, int length, int k) 54 { 55 int number = 0; 56 if (data != NULL || length > 0) 57 { 58 int FirstIndex = GetFirstK(data, k, length); 59 printf("first index is %d\n", FirstIndex); 60 int LastIndex = GetLastK(data, k, length); 61 printf("last index is %d\n", LastIndex); 62 if (FirstIndex > -1 && LastIndex > -1) 63 number = LastIndex - FirstIndex + 1; 64 } 65 return number; 66 } 67 68 int main() 69 { 70 int data[] = {1, 3, 3, 3, 4, 5, 6}; 71 int num = GetNumOfK(data, 7, 5); 72 printf("Num of 5 is %d\n", num); 73 }