循环有序数组中最小元素的查找(二分查找)

问题描述:

如题,其中循环有序数组指的是对有序数组进行循环移位后的结果,如[7,8,9,0,1,2,3,4,5,6];

实现思路:

由循环有序数组结构可知,若数组不为整体有序,则最小值一定是处于无序子序列之中,如上述例子中,最小值一定处于7到1之间,而一定不处于1到6之间,根据该性质可以得到如下算法:

先进行判断该数组是否整体有序(arr[left] < arr[right]),若有序返回left即可。

对于整体无序情况(arr[left] < arr[right]),mid = left + (right - left) / 2,判断left - mid 和 mid - right是否为有序,

若arr[mid] > arr[right] 对mid - right部分进行查找,arr[mid] < arr[left] 对left - mid 部分进行查找.;

若以上条件均不满足即(arr[mid] <= arr[right] && arr[mid] >= arr[left]),又由于arr[left] >=arr[right] 所以可得:

arr[mid] = arr[left] = arr[right],对于该情况只能采用从头到尾的方式进行搜索了。

具体实现代码如下:

     public static int selution(int[] arr) {
         int left = 0, right = arr.length - 1, mid = 0;
         while (right - left > 1) {
             if (arr[left] < arr[right]) {
                 return left;
             }
             mid = left + (right - left) / 2;
             // arr[left] >= arr[right]
             if (arr[mid] < arr[left]) { //最小值在左端
                 right = mid;
             }
             if (arr[mid] > arr[right]) { //最小值在后面
                 left = mid;
             }
             if (arr[mid] >= arr[left] && arr[mid] <= arr[right]) {
                 //即 arr[right] = arr[left] = arr[mid]
                 return findMin(arr, left, right);
             }
         }
         return  arr[left] < arr[right] ? left : right;// 返回left right 中最小的
     }
     public static int findMin(int[] arr, int left, int right){
         int minIndex = left ,min = arr[left];
         for (int i = left + 1; i <= right; i++) {
             if(arr[i] < min) {
                 min = arr[i];
                 minIndex = i;
             }
         }
         return minIndex;
     }
扫描二维码关注公众号,回复: 9812091 查看本文章
发布了38 篇原创文章 · 获赞 4 · 访问量 2143

猜你喜欢

转载自blog.csdn.net/gw_9527/article/details/103091323