搜索旋转排序数组1
假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。你的算法时间复杂度必须是 O(log n) 级别。
示例 1:
输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例 2:
输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1
法一:旋转数组中找目标值」 转化成了 「有序数组中找目标值」
题解:
nums = [4,5,6,7,0,1,2]
1.先根据num[0]和target关系判断是在左半段还是右半段
2.再根据num[0]和num[mid]关系判断mid在左边还是右边
3.target在左,mid在右,target = 5, 目标值在左半段,因此在 [4, 5, 6, 7, inf, inf, inf] 这个有序数组里找就行了;
4.target在右,mid在左,target = 1, 目标值在右半段,因此在 [-inf, -inf, -inf, -inf, 0, 1, 2]
class Solution {
public int search(int[] nums, int target) {
int low=0;
int hight=nums.length-1;
while(low<=hight){
int mid=low+(hight-low)/2;
if(nums[mid]==target){
return mid;
}
//先根据num[0]和target关系判断是在左半段还是右半段
//比num[0]大的在左,比num[0]小的在右,
//说明target在左半段
if(target>=nums[0]){
//mid在右边,置为最大值,变成一个有序数组
if(nums[mid]<nums[0]){
nums[mid]=Integer.MAX_VALUE;
}
}else{
//说明target在右半段
//mid在左边,置为最小值,变成一个有序数组
if(nums[mid]>=nums[0]){
nums[mid]=Integer.MIN_VALUE;
}
}
if(target<nums[mid]){
hight=mid-1;
}else{
low=mid+1;
}
}
return -1;
}
}
思路二:直接对旋转数组进行二分查找。
思路:
1.先根据num[low]和num[mid]关系判断mid是在左半段还是右半段
2.再根据target来确定low和high的位置
3.mid在左,target在nums[low]~nums[mid]之间,hight=mid-1
4.mid在左,target不在nums[low]~nums[mid]之间,low=mid+1
5.mid在右,target在nums[mid]~nums[hight]之间,low=mid+1
6.mid在右,target不在nums[mid]~nums[hight]之间,hight=mid-1
class Solution {
public int search(int[] nums, int target) {
int low = 0;
int hight = nums.length - 1;
int mid=0;
while (low <= hight) {
mid = low + (hight - low) / 2;
if (nums[mid] == target) {
return mid;
}
//先根据num[low]和num[mid]关系判断mid是在左半段还是右半段,再根据target来确定low和high的位置
//说明mid在左半段
if (nums[low] <= nums[mid]) {
//target在low和mid中间,改变hight
if (nums[low] <=target && target < nums[mid]) {
hight = mid - 1;
}else{
low=mid+1;
}
} else {
//说明mid在右半段
//target在mid和hight中间,改变low
if (nums[mid] < target && target <= nums[hight]) {
low = mid + 1;
}else{
hight=mid-1;
}
}
}
return -1;
}
}
搜索旋转排序数组2
假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [0,0,1,2,2,5,6] 可能变为[2,5,6,0,0,1,2] )。
编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。nums可能包含重复元素。
解题思路:
1.情况一:当low和mid一样,分不清到底是前面有序还是后面有序,low++,相当于去掉一个重复的干扰项
2.先根据num[low]和num[mid]关系判断mid是在左半段还是右半段
3.再根据target来确定low和high的位置
4.情况二:
mid在左,target在nums[low]~nums[mid]之间,hight=mid-1
mid在左,target不在nums[low]~nums[mid]之间,low=mid+1
6.情况三:
mid在右,target在nums[mid]~nums[hight]之间,low=mid+1
mid在右,target不在nums[mid]~nums[hight]之间,hight=mid-1
import java.util.*;
class Solution {
public boolean search(int[] nums, int target) {
int low = 0;
int hight = nums.length - 1;
int mid=0;
while (low <= hight) {
mid = low + (hight - low) / 2;
if (nums[mid] == target) {
return true;
}
//情况一:当low和mid一样,分不清到底是前面有序还是后面有序,low++,相当于去掉一个重复的干扰项
if(nums[low] == nums[mid]){
low++;
continue;
}
//情况二:
//先根据num[low]和num[mid]关系判断mid是在左半段还是右半段,再根据target来确定low和high的位置
//说明mid在左半段
if (nums[low] <= nums[mid]) {
//target在low和mid中间,改变hight
if (nums[low] <=target && target < nums[mid]) {
hight = mid - 1;
}else{
low=mid+1;
}
} else {
//情况三:
//说明mid在右半段
//target在mid和hight中间,改变low
if (nums[mid] < target && target <= nums[hight]) {
low = mid + 1;
}else{
hight=mid-1;
}
}
}
return false;
}
}