Leetcode面试题 10.03. 搜索旋转数组-----二分搜索

题目表述

搜索旋转数组。给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。

示例:

输入: arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 5
输出: 8(元素5在该数组中的索引)

二分搜搜

  • 每次取中间索引判断是否和target相等,如果相等,则继续将target往左遍历,遍历到最小和target相等的索引然后返回

如果不等:则判断midVal和rVal(右边界的值),此时有三种可能:

  • midVal<rVal,则可以说明mid~right一定是递增的,则判断target是否是大于midVal并且小于等于rVal,即是否在(mid,right]这个区间,如果是,压缩区间left=mid+1,否则说明不在(mid,right]区间,压缩区间 [left,mid)

  • midVal>rVal,则可以说明leftmid是递增的,因为原数组是非递减的,要满足中间数值大于最右边数值,那么最大值一定不在midVal的左侧(假如在左侧,那么有leftk)递增,然后k+1(k<mid)~right递增。处理方式同上

  • midVal==rVal,则有两种可能 right0mid 的值都相等,或者 mid~right的值相等,无论是哪种,都可以将right舍去,压缩区间

class Solution {
    public int search(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1;
        if(arr[0] == target) return 0;
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(arr[mid] == target){
                while(mid > 0 && arr[mid - 1] == target) mid--;
                return mid;
            }
            if(arr[mid] == arr[left] ){
                left++;
            }
            else if(arr[mid] >= arr[left]){
                if(target >= arr[left] && target <= arr[mid]){
                    right = mid  - 1;
                }else{
                    left = mid + 1;
                }
            }else{
                if(arr[mid] <= target && target <= arr[right]){
                    left = mid + 1;
                }else{
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
}
posted @ 2022-06-20 21:05  YoungerWb  阅读(31)  评论(0)    收藏  举报