《Cracking the Coding Interview》——第11章:排序和搜索——题目3

2014-03-21 20:55

题目:给定一个旋转过的升序排序好的数组,不知道旋转了几位。找出其中是否存在某一个值。

解法1:如果数组的元素都不重复,那么我的解法是先找出旋转的偏移量,然后进行带偏移量的二分搜索。两个过程都是对数级的。

代码:

 1 // 11.3 Given a sorted array rotated by a few positions, find out if a value exists in the array.

 2 // Suppose all elements in the array are unique.

 3 #include <algorithm>

 4 #include <vector>

 5 #include <cstdio>

 6 using namespace std;

 7 

 8 int rotatedBinarySearch(vector<int> &v, int n, int key)

 9 {

10     int offset;

11     

12     if ((int)v.size() < n || n <= 0) {

13         return -1;

14     }

15     

16     int ll, rr, mm;

17 

18     if (v[0] < v[n - 1]) {

19         offset = 0;

20     } else {

21         ll = 0;

22         rr = n - 1;

23         while (rr - ll > 1) {

24             mm = (ll + rr) / 2;

25             if (v[mm] > v[ll]) {

26                 ll = mm;

27             } else {

28                 rr = mm;

29             }

30         }

31         offset = rr;

32     }

33     

34     ll = 0;

35     rr = n - 1;

36     while (ll <= rr) {

37         mm = (ll + rr) / 2;

38         if (key < v[(mm + offset) % n]) {

39             rr = mm - 1;

40         } else if (key > v[(mm + offset) % n]) {

41             ll = mm + 1;

42         } else {

43             return (mm + offset) % n;

44         }

45     }

46     return -1;

47 }

48 

49 int main()

50 {

51     int n;

52     int i;

53     vector<int> v;

54     

55     while (scanf("%d", &n) == 1 && n > 0) {

56         v.resize(n);

57         for (i = 0; i < n; ++i) {

58             scanf("%d", &v[i]);

59         }

60         scanf("%d", &i);

61         printf("%d\n", rotatedBinarySearch(v, n, i));

62     }

63     

64     return 0;

65 }

解法2:如果数组的元素可能存在重复,那么我的思路仍然是先二分查找找出偏移量,然后执行带偏移量的二分搜索。不过,在找偏移量的过程中可能会出现无法决定向左还是向右的情况,比如这两个例子{1, 3, 1, 1, 1}{1, 1, 1, 3, 1},在第一次二分时,左中右的元素都是‘1’,无法确定应该往哪边走。这时就得扫描整段,{1, 1, 1}全部是同一元素,{1, 3, 1}存在不同元素,所以应该选择{1, 3, 1}进行二分,因为在首尾相同的情况下,中间如果有不同元素的话,表示旋转的偏移量应该会落在这个区间里。找到偏移量以后,之后的查找就是严格二分的了。

代码:

  1 // 11.3 Given a sorted array rotated by a few positions, find out if a value exists in the array.

  2 // Suppose the array may contain duplicates, what's it gonna be then?

  3 #include <algorithm>

  4 #include <vector>

  5 #include <cstdio>

  6 using namespace std;

  7 

  8 int rotatedBinarySearch(vector<int> &v, int n, int key)

  9 {

 10     int offset;

 11     

 12     if ((int)v.size() < n || n <= 0) {

 13         return -1;

 14     }

 15     

 16     int ll, rr, mm;

 17     int i;

 18     

 19     ll = 0;

 20     rr = n - 1;

 21     while (rr - ll > 1 && v[ll] == v[rr]) {

 22         mm = (ll + rr) / 2;

 23         if (v[mm] > v[ll]) {

 24             ll = mm;

 25             break;

 26         } else if (v[mm] < v[ll]) {

 27             rr = mm;

 28             break;

 29         } else {

 30             for (i = ll; i < mm - 1; ++i) {

 31                 if (v[i] != v[i + 1]) {

 32                     break;

 33                 }

 34             }

 35             if (i < mm - 1) {

 36                 rr = mm;

 37                 break;

 38             }

 39             for (i = mm; i < rr - 1; ++i) {

 40                 if (v[i] != v[i + 1]) {

 41                     break;

 42                 }

 43             }

 44             if (i < rr - 1) {

 45                 break;

 46             }

 47             

 48             // if all elements are the same, it ends here

 49             return (v[0] == key) ? 0 : -1;

 50         }

 51     }

 52     

 53     if (v[ll] < v[rr]) {

 54         offset = 0;

 55     } else {

 56         // here it is guaranteed v[ll] != v[rr]

 57         while (rr - ll > 1) {

 58             mm = (ll + rr) / 2;

 59             if (v[mm] >= v[ll]) {

 60                 ll = mm;

 61             } else {

 62                 rr = mm;

 63             }

 64         }

 65         offset = rr;

 66     }

 67     

 68     // the binary search part remains the same, difference lies in how we find the 'offset'.

 69     ll = 0;

 70     rr = n - 1;

 71     while (ll <= rr) {

 72         mm = (ll + rr) / 2;

 73         if (key < v[(mm + offset) % n]) {

 74             rr = mm - 1;

 75         } else if (key > v[(mm + offset) % n]) {

 76             ll = mm + 1;

 77         } else {

 78             return (mm + offset) % n;

 79         }

 80     }

 81 

 82     return -1;

 83 }

 84 

 85 int main()

 86 {

 87     int n;

 88     int i;

 89     vector<int> v;

 90     

 91     while (scanf("%d", &n) == 1 && n > 0) {

 92         v.resize(n);

 93         for (i = 0; i < n; ++i) {

 94             scanf("%d", &v[i]);

 95         }

 96         scanf("%d", &i);

 97         printf("%d\n", rotatedBinarySearch(v, n, i));

 98     }

 99     

100     return 0;

101 }

 

你可能感兴趣的:(interview)