LeetCode33. 搜索旋转排序数组
题目描述
/**
*
* 整数数组 nums 按升序排列,数组中的值 互不相同 。
* <p>
* 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,
* 使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]
* (下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
* <p>
* 给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,
* 则返回它的下标,否则返回 -1 。
*
*/
思路分析
- 此题目中原数组是顺序排列的,但是经旋转后数组不绝对顺序排列
- 由题目可知,将此旋转后的数组从中间分开后,总能保证有一半是顺序的,而另一半则是没有排序的
- 因此顺序的一半可以使用二分查找,不过要先判断target是否在这个顺序的一半数组中
- 如果在顺序的数组中,则直接二分查找,否则重新将另一半没有排序的数组从中间分开,仍然能保证一半是顺序的,一般是没有顺序的,依次上述方法即可
- 实现如下
源码及分析
//思路分析:局部二分查找
/**
*
* @param nums 要查找的旋转数组
* @param target 目标值
* @return 返回的元素位置,索引
*/
public int search(int[] nums, int target) {
//定义变量保存数组长度
int len = nums.length;
//数据校验
if (nums == null || len == 0) {
return -1;
}
//目标值所在的索引
int index = -1;
//数组左右边界下标
int left = 0, right = len - 1;
while (left <= right) {
//数组中间元素的大小
int mid = (left + right) / 2;
//判断数组前半部分有序还是后半部分有序,如果前半部分有序
if (nums[mid] >= nums[left]) {
//判断target是否在此区间
if (target >= nums[left] && target <= nums[mid]) {
//如果在此区间,查找target值
if (nums[mid] == target) {
index = mid;
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
//如果不在此区间,缩小查找范围
} else {
left = mid + 1;
}
} else {
//如果后半部分有序
//判断target是否在此区间
if (target >= nums[mid] && target <= nums[right]) {
if (nums[mid] == target) {
index = mid;
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
} else {
right = mid - 1;
}
}
}
return index;
}