本文涉及 4 道「搜索旋转排序数组」题:
- LeetCode 33 题:搜索旋转排序数组
- LeetCode 81 题:搜索旋转排序数组-ii
- LeetCode 153 题:寻找旋转排序数组中的最小值
- LeetCode 154 题:寻找旋转排序数组中的最小值-ii
可以分为 3 类:
- 33、81 题:搜索特定值
- 153、154 题:搜索最小值
- 81、154 题:包含重复元素
- LeetCode 33 题:搜索旋转排序数组
-
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,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] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 -
class Solution { public int search(int[] nums, int target) { int low = 0; int high = nums.length - 1; while (low <= high) { int mid = low + (high - low) / 2; if (nums[mid]==target) return mid; else if (nums[low]<=nums[mid]){ if (nums[low] <= target && target <=nums[mid]) high = mid-1; else low = mid+1; }else{ if (nums[mid] <= target && target <=nums[high]) low = mid+1; else high = mid -1; } } return -1; } }
- LeetCode 81 题:搜索旋转排序数组-ii (会有重复数)
-
对于数组中有重复元素的情况,二分查找时可能会有 a[l]=a[mid]=a[r]。
例如 \nums=[3,1,2,3,3,3,3],target=2,首次二分时无法判断区间 [0,3] 和区间 [4,6] 哪个是有序的。
对于这种情况,我们只能将当前二分区间的左边界加一,右边界减一,然后在新区间上继续二分查找。
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/solution/sou-suo-xuan-zhuan-pai-xu-shu-zu-ii-by-l-0nmp/
-
class Solution { public boolean search(int[] nums, int target) { int n = nums.length; if (n == 0) { return false; } int l = 0, r = n - 1; while (l <= r) { int mid = (l + r) / 2; if (nums[mid] == target) { return true; } if (nums[l] == nums[mid] && nums[mid] == nums[r]) { ++l; --r; } else if (nums[l] <= nums[mid]) { if (nums[l] <= target && target < nums[mid]) { r = mid - 1; } else { l = mid + 1; } } else { if (nums[mid] < target && target <= nums[n - 1]) { l = mid + 1; } else { r = mid - 1; } } } return false; } }
- LeetCode 153 题:寻找旋转排序数组中的最小值
- 如果中值比右边的值还大,有旋转在右边,left=mid+1;
- 否则 慢慢缩小右边界
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] > nums[right]) {
left = mid + 1;
} else {
right = mid;
}
}
return nums[left];
}
};
- LeetCode 154 题:寻找旋转排序数组中的最小值-ii
- 与上一题类似 可能有重复数组 当数值重复的时候 右边界--,去掉重复
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] > nums[right]) {
left = mid + 1;
} else if(nums[mid] < nums[right]){
right = mid;
}else{
right --;
}
}
return nums[left];
}
};