「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」
描述
搜索旋转数组。给定一个排序后的数组,包含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]之间
解析
使用旋转数组,就是数组至少有一半是有序的,因此当每次二分后只需要判断索要寻找的目标是否在有序的那一般数组中即可;
- 如果 target 在有序的那一半数组中,则我们直接去这一半数组中寻找即可。
- 如果 target 不在有序的那一半数组中,则我们只需要去另一半数组中去寻找即可。
- 特别小心数组中有大量的重复元素的情形,此时我们需要判断数组的下标 mid 是否和数组的边界相等。如 [1,1,1,1,1,2,3,1,1] 这种情况下我们需要将数组缩短,直到下标 mid 和边界不相等为止。
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
if (right == -1)
return -1;
// 循环结束条件left==right
while (left < right) {
int mid = left + (right - left) / 2;
// 如果左值小于中值,说明左边区间升序
if (nums[left] < nums[mid]) {
if (nums[left] <= target && target <= nums[mid]) {
right = mid;
} else {
left = mid + 1;
}
} else if (nums[left] > nums[mid]) {
if (nums[left] <= target || target <= nums[mid]) {
right = mid;
} else {
left = mid + 1;
}
} else if (nums[left] == nums[mid]) {
if (nums[left] != target) {
left++;
} else {
right = left;
}
}
}
// 返回left,或者-1
return (nums[left] == target) ? left : -1;
}
}
运行结果:
执行结果:通过
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:39 MB, 在所有 Java 提交中击败了70.90%的用户