循环有序数组算法

问题:

 

有一个循环有序数组A,如{7,8,9,0,1,2,3,4,5,6},不知道其最小值的位置。

 

那么如何从这样的数组中寻找一个特定的元素呢?

 

解决:

 

当然,遍历总是一个办法。当然面试的时候回答遍历估计就直接杯具了。

 

我的想法是将原数组分段,用首元素s,中间元素m和尾元素e,可以将数组分为两个子数组s1,s2

 

那么,必然有至少一个子数组是有序的。那么如何确定那一段是有序的呢?

 

通过分析可以看到只有3种情况:

 

●当s就是A中最小的元素时,以下不等式成立:

 

  s <= m <= e

 

●当最小值位于(s, m]时,则有:

 

  m <= e <= s

 

●当最小值出现在(m,e]时,则有:

 

  e <= s <= m

 

所以通过s,m,e的大小关系,可以很轻松的判断出s1s2哪个是有序的。

 

通过比较要查找的目标t s,m,e的大小关系,可以知道t位于哪个子数组。

 

t位于有序的子数组,则用二分查找就可以了。

 

否则,对无序的子数组重复刚才的过程就可以了。

 

具体代码如下:

 

view plaincopy to clipboardprint?

01.#include <stdlib.h>  

02.#include <stdio.h>  

03.int binarySearch(int target, int array[], int start, int end)  

04.{  

05.    int mid = -1;  

06.    int l = start - 1;  

07.    int r = end + 1;  

08.    while(l+1 != r) {  

09.        mid = l + (r - l) / 2;  

10.        if(array[mid] < target) {  

11.            l = mid;  

12.        } else {  

13.            r = mid;  

14.        }  

15.    }  

16.    if(r <= end && array[r] == target) {  

17.        return r;  

18.    } else {  

19.        return -1;  

20.    }  

21.}  

22.int search(int target, int array[], int start, int end)  

23.{  

24.    if(start > end){  

25.        return -1;  

26.    }  

27.    int mid = start + (end - start) / 2;  

28.    int s = array[start];  

29.    int m = array[mid];  

30.    int e = array[end];  

31.    if(s <= m) {  

32.        if(s <= e) { //mini value is at start  

33.            return binarySearch(target, array, start, end);  

34.        } else { //mini value is in range (mid, end]  

35.            if(target >=s && target <= m) {  

36.                return binarySearch(target, array, start, mid);  

37.            } else {  

38.                return search(target, array, mid+1, end);  

39.            }  

40.        }  

41.    } else { //mini value is in range (start, mid]  

42.            if(target > m && target <= e) {  

43.                return binarySearch(target, array, mid + 1, end);  

44.            } else {  

45.                return search(target, array, start, mid);  

46.            }  

47.    }  

48.}  

49.int main(int argc, char* argv[])  

50.{  

51.    int t1[] = {7,8,9,0,1,2,3,4,5,6};  

52.    int i = -1;  

53.    int index = -1;  

54.    for(; i< 11; i++) {  

55.        index = search(i, t1, 0, 9);  

56.        printf("Find %d at index %d!/n", i, index);  

57.    }  

58.    return 0;  

59.} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值