题号: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);
}
}
}
}