二分查找及拓展

  1. 请快速写出二分查找的代码。
  2. 把一个数组最开始的若干个元素搬到数组的末尾,叫数组的旋转。输入一个递增排序的数组的一个旋转,输出数组的最小元素。(8)
  3. 统计一个数字在排序数组中出现的次数。(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 }

 

 

posted on 2013-03-27 14:29  月moon鸟  阅读(181)  评论(0编辑  收藏  举报

导航