leetcode--search_in_rotated_sorted_array

33 篇文章 0 订阅
27 篇文章 0 订阅

题意: 假设有一个排好序的数组,在某个你不知道的地方进行了旋转。给定一个需要查找的目标值,如果能找到就返回它的索引,否则返回-1。该数组中没有重复的值。
举例

数组(0, 1, 2, 4, 5, 6, 7)旋转后变成(4, 5, 6, 7, 0, 1, 2)。
查找5,返回1;
查找1,返回5;
查找3,返回-1;

分析: 首先最简单的,遍历一趟整个数组,查找目标值,时间复杂度为O(n)。那么有没有效率更高的呢?答案肯定是有的,那就是二分搜索。解决该问题需要两次二分搜索,第一次二分用来找到那个旋转点,比如例子中的那个’0’在数组中的位置4即为旋转点,用来判断是否为旋转点的条件是index位置的值大于index + 1位置的值(index + 1是旋转点)。第二次二分用于查找目标值,首先将该数组根据旋转点划分成两个,如上例中可以按位置划分成[0, …, 3]和 [4, …, 6]两个,判断目标值在其中的哪个区间,在该区间内二分查找即可。

代码

public int search(int[] A, int target) {
        int pivot_index = searchPivot(A, 0, A.length - 1);  //获得旋转点所在位置
        if(target >= A[pivot_index] && target <= A[A.length - 1]){//查找target
            return binarySearch(A, pivot_index, A.length - 1, target);
        }else if(pivot_index > 0 && target >= A[0] && target <= A[pivot_index - 1]){
            return binarySearch(A, 0, pivot_index - 1, target);
        }else{
            return -1;
        }
    }

    /**
     * 二分找到旋转点,如果没有就返回0
     */
    public int searchPivot(int[] A, int begin, int end){
        if(begin > end) return 0;   //如果找不到pivot,则表示该数组没有旋转
        else{
            int mid = (begin + end) / 2;
            if(mid < A.length - 1 && A[mid] > A[mid + 1]){
                return mid + 1;
            }else{
                int left = searchPivot(A, begin, mid - 1);  //分治找左边
                int right = searchPivot(A, mid + 1, end);   //分治找右边
                if(left != 0){
                    return left;
                }else if(right != 0){
                    return right;
                }else{
                    return 0;
                }
            }
        }
    }

    /**
     * 二分查找target
     */
    public int binarySearch(int[]A, int begin, int end, int target){
        if(begin > end) return -1;
        else{
            int mid = (begin + end) /2;
            if(A[mid] == target) return mid;
            else{
                if(A[mid] > target) return binarySearch(A, begin, mid - 1, target);
                else return binarySearch(A, mid + 1, end, target);
            }
        }
    }

源程序下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值