[算法练习及思路-程序员面试金典(Java解法)]No57.搜索旋转数组

题号:no57

题目名:搜索旋转数组
原题URL:https://leetcode-cn.com/problems/search-rotate-array-lcci/
题目描述

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

示例

示例 1:

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

示例 2:

 输入:arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 11
 输出:-1 (没有找到)
限制
  • arr 长度范围在[1, 1000000]之间
思路

1.首先要明确一点,无论经过多少次旋转,肯定最后有一边有序,另一边无序.

2.这里主要难点就是会有重复字符,需要去重.

3.二分+递归+去重完事

解题代码
public class Solution {
    public int search(int[] arr, int target) {
        if (arr == null || arr.length == 0) return -1;
        int search = search(0, arr.length - 1, arr, target);
        return search <0?-1:search;
    }

    private int search(int start, int end, int[] arr, int target) {
        if(start>end) return -1;
        //有可能要找的数就在头和尾部
        if(target==arr[start]) return start;
        if(target==arr[end]) {
            while (arr[end]==target) {
                end--;
            }
            return end+1;
        }
        //去掉重复数字
        while (arr[start]==arr[end]) {
            start++;
            end--;
            return search(start, end, arr, target);
        }
        //进行排序,保证左右两边肯定有一侧是有序的
        int mid = (start+end)/2;
        //前半部分有序的话,就是末尾的值大于首部的值
        if(arr[mid]>arr[start]) {
            //有序后不再范围内,在剩下的乱序范围里面找
            if(target>arr[mid]||target < arr[0]) {
                return search(mid+1,end,arr,target);
            }else {
                //在范围内,找到就是有,没找到就是乱序
                return Arrays.binarySearch(arr,start,mid,target);
            }
        }else {
            //后半部分有序
            if(target>arr[end]||target <arr[mid]) {
                return search(start,mid,arr,target);
            }else {
                //在范围内,找到就是有,没找到就是乱序
                return Arrays.binarySearch(arr,mid,end,target);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值